EF学习笔记——生成自定义实体类

35 篇文章 0 订阅

使用EF,采用DataBase 模式,实体类都是按照数据库的定义自动生成,我们似乎无法干预。如果要生成自定义的实体类,该怎么做呢?

思路是这样的:

1、我们要自定义生成的实体类,都是分部类(partial),目的是对EF生成的实体类进行扩充;

2、扩充部分,预先写好在模板里,自动生成

3、每个实体类,都进行扩充

实施方法:

1、给VS2012安装两个插件:

**Devart T4 Editor:为VS提供智能提示功能。
T4 Toolbox:在生成多文件时很有用。**

2、新建文件夹T4,存放模板文件

1)创建T4 Toolbox模板文件EntityTemplate.tt,作用是生成多个实体类文件

代码如下:

   <#+  
    // <copyright file="Entity.tt" company="cqxm">  
    //  Copyright © . All Rights Reserved.  
    // </copyright>  

    public class Entity : CSharpTemplate  
    {  
        private string _className;  

        public Entity(string className)  
        {  
            _className = className;  
        }  

        public override string TransformText()  
        {  
            base.TransformText();  
    #>  
    namespace testEF  
    {  
        public partial class <#= _className #> : IEntity  
        {  
            public string _ID   
            {  
                get  
                {  
                    return Id.ToString();  
                }  
            }  
        }  
    }  
    <#+  
            return this.GenerationEnvironment.ToString();  
        }  
    }  
    #>  

2)创建T4模板文件EntityOutput.tt,调用前面写的EntityTemplate.tt,真正生成各种实体类文件

[csharp] view plaincopy在CODE上查看代码片派生到我的代码片

  <#@ template debug="false" hostspecific="false" language="C#" #>  
    <#@ assembly name="System.Core" #>  
    <#@ import namespace="System.IO" #>  
    <#@ import namespace="System.Linq" #>  
    <#@ import namespace="System.Text" #>  
    <#@ import namespace="System.Collections.Generic" #>  
    <#@ include file="EF.Utility.CS.ttinclude"#>  
    <#@ include file="T4Toolbox.tt" #>  
    <#@ include file="EntityTemplate.tt" #>  
    <#  
        string curPath = Path.GetDirectoryName(Host.TemplateFile);  
        string destPath = Path.Combine(curPath, @"..\Partial");//将各个扩充实体类文件生成到文件夹Partial下  
        if(!Directory.Exists(destPath))  
        {  
            Directory.CreateDirectory(destPath);  
        }  
        const string inputFile = @"..\ShowMe.edmx";  
        var textTransform = DynamicTextTransformation.Create(this);  
        var itemCollection = new EdmMetadataLoader(textTransform.Host, textTransform.Errors).CreateEdmItemCollection(inputFile);  
        foreach (var entity in GetItemsToGenerate<EntityType>(itemCollection))  
        {//每个实体类都要自动生成扩充文件,是自动哦,参考文章里介绍的是手动输入实体类名称  
            Entity template = new Entity(entity.Name);  
            string fileName = string.Format(@"{0}\{1}.cs", destPath, entity.Name);  
            template.Output.Encoding = Encoding.UTF8;  
            if(File.Exists(fileName))  
            {  
                File.Delete(fileName);  
            }  
            template.RenderToFile(fileName);  
        }  
    #>  

    <#+  
    /*以下代码都是为了获得EF自动生成的所有实体类名单,抄自 *.edmx\*.Context.tt。 
    没办法,谁叫俺看不懂哪些代码呢 
    */  
    public class EdmMetadataLoader  
    {  
        private readonly IDynamicHost _host;  
        private readonly System.Collections.IList _errors;  

        public EdmMetadataLoader(IDynamicHost host, System.Collections.IList errors)  
        {  
            ArgumentNotNull(host, "host");  
            ArgumentNotNull(errors, "errors");  

            _host = host;  
            _errors = errors;  
        }  

        public IEnumerable<GlobalItem> CreateEdmItemCollection(string sourcePath)  
        {  
            ArgumentNotNull(sourcePath, "sourcePath");  

            if (!ValidateInputPath(sourcePath))  
            {  
                return new EdmItemCollection();  
            }  

            var schemaElement = LoadRootElement(_host.ResolvePath(sourcePath));  
            if (schemaElement != null)  
            {  
                using (var reader = schemaElement.CreateReader())  
                {  
                    IList<EdmSchemaError> errors;  
                    var itemCollection = MetadataItemCollectionFactory.CreateEdmItemCollection(new[] { reader }, out errors);  

                    ProcessErrors(errors, sourcePath);  

                    return itemCollection;  
                }  
            }  
            return new EdmItemCollection();  
        }  

        public string GetModelNamespace(string sourcePath)  
        {  
            ArgumentNotNull(sourcePath, "sourcePath");  

            if (!ValidateInputPath(sourcePath))  
            {  
                return string.Empty;  
            }  

            var model = LoadRootElement(_host.ResolvePath(sourcePath));  
            if (model == null)  
            {  
                return string.Empty;  
            }  

            var attribute = model.Attribute("Namespace");  
            return attribute != null ? attribute.Value : "";  
        }  

        private bool ValidateInputPath(string sourcePath)  
        {  
            if (sourcePath == "$" + "edmxInputFile" + "$")  
            {  
                _errors.Add(  
                    new CompilerError(_host.TemplateFile ?? sourcePath, 0, 0, string.Empty,  
                        GetResourceString("Template_ReplaceVsItemTemplateToken")));  
                return false;  
            }  

            return true;  
        }  

        public XElement LoadRootElement(string sourcePath)  
        {  
            ArgumentNotNull(sourcePath, "sourcePath");  

            var root = XElement.Load(sourcePath, LoadOptions.SetBaseUri | LoadOptions.SetLineInfo);  
            return root.Elements()  
                .Where(e => e.Name.LocalName == "Runtime")  
                .Elements()  
                .Where(e => e.Name.LocalName == "ConceptualModels")  
                .Elements()  
                .Where(e => e.Name.LocalName == "Schema")  
                .FirstOrDefault()  
                    ?? root;  
        }  

        private void ProcessErrors(IEnumerable<EdmSchemaError> errors, string sourceFilePath)  
        {  
            foreach (var error in errors)  
            {  
                _errors.Add(  
                    new CompilerError(  
                        error.SchemaLocation ?? sourceFilePath,  
                        error.Line,  
                        error.Column,  
                        error.ErrorCode.ToString(CultureInfo.InvariantCulture),  
                        error.Message)  
                    {  
                        IsWarning = error.Severity == EdmSchemaErrorSeverity.Warning  
                    });  
            }  
        }  

        public bool IsLazyLoadingEnabled(EntityContainer container)  
        {  
            string lazyLoadingAttributeValue;  
            var lazyLoadingAttributeName = MetadataConstants.EDM_ANNOTATION_09_02 + ":LazyLoadingEnabled";  
            bool isLazyLoading;  
            return !MetadataTools.TryGetStringMetadataPropertySetting(container, lazyLoadingAttributeName, out lazyLoadingAttributeValue)  
                || !bool.TryParse(lazyLoadingAttributeValue, out isLazyLoading)  
                || isLazyLoading;  
        }  
    }  

    public static void ArgumentNotNull<T>(T arg, string name) where T : class  
    {  
        if (arg == null)  
        {  
            throw new ArgumentNullException(name);  
        }  
    }  

    private static readonly Lazy<System.Resources.ResourceManager> ResourceManager =  
        new Lazy<System.Resources.ResourceManager>(  
            () => new System.Resources.ResourceManager("System.Data.Entity.Design", typeof(MetadataItemCollectionFactory).Assembly), isThreadSafe: true);  

    public static string GetResourceString(string resourceName)  
    {  
        ArgumentNotNull(resourceName, "resourceName");  

        return ResourceManager.Value.GetString(resourceName, null);  
    }  
    private const string ExternalTypeNameAttributeName = @"http://schemas.microsoft.com/ado/2006/04/codegeneration:ExternalTypeName";  
    public IEnumerable<T> GetItemsToGenerate<T>(IEnumerable<GlobalItem> itemCollection) where T: EdmType  
    {  
        return itemCollection  
            .OfType<T>()  
            .Where(i => !i.MetadataProperties.Any(p => p.Name == ExternalTypeNameAttributeName))  
            .OrderBy(i => i.Name);  
    }  
    #>  

生成各种实体类文件的方法很简单,只要保存一下这个EntityOutput.tt文件,各种实体类文件即可应声生成,很爽。

最后生成的文件如蓝线圈圈所示

某个实体扩充类:

    // <autogenerated>  
    //   This file was generated by T4 code generator EntityOutput.tt.  
    //   Any changes made to this file manually will be lost next time the file is regenerated.  
    // </autogenerated>  

    namespace testEF  
    {  
        public partial class Show : IEntity  
        {  
            public string _ID   
            {  
                get  
                {  
                    return Id.ToString();  
                }  
            }  
        }  
    }  

这个模板文件看起来好复杂,事实上,绝大部分都是自动生成,和拷贝过来的,我自己其实并不懂。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
EF Core框架中,数据库表的列名和实体类的属性名不一致是一个常见的情况。这种情况可能出现在数据库设计时,为了符合统一的命名规范,数据库表的列名可能使用下划线分隔,而实体类的属性名可能使用驼峰命名法。 为了解决这个问题,EF Core提供了一些特性和约定,可以映射数据库列名和实体类属性名之间的关系。其中最常用的特性是`Column`和`Table`特性。 `Column`特性用于将实体类的属性映射到数据库表的列名。例如,如果数据库表中的列名是`first_name`,而实体类中的属性名是`FirstName`,可以在实体类的属性上使用`[Column("first_name")]`特性来进行映射。 `Table`特性用于将实体类映射到数据库表的名称。如果数据库表的名称与实体类的名称不一致,可以在实体类上使用`[Table("table_name")]`特性来指定对应的表名。 除了特性,EF Core还支持一些约定,根据命名规则自动进行映射。例如,默认情况下,EF Core会将实体类的属性名映射到数据库表的列名,只需保证它们的名称一致即可。如果数据库列名是多个单词的组合,使用下划线分隔,EF Core会将其转换为驼峰命名法。 总结来说,EF Core提供了特性和约定来处理数据库列名和实体类列名不一致的情况。通过使用`Column`和`Table`特性、遵循命名约定,可以实现灵活的映射,确保数据在实体类和数据库表之间的正确转换。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值