ReverseEngineerCodeFirst 自定义模板

Posted OMI天空

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ReverseEngineerCodeFirst 自定义模板相关的知识,希望对你有一定的参考价值。

1.在你要生成的项目里面在根目录下面添加CodeTemplates文件夹,并在该文件夹下面创建子文件夹ReverseEngineerCodeFirst

2.在ReverseEngineerCodeFirst目录下面新建一下几个文件:

  • Context.tt
  •  1 <#@ template hostspecific="true" language="C#" #>
     2 <#@ include file="EF.Utility.CS.ttinclude" #><#@
     3  output extension=".cs" encoding="UTF-8" #><#
     4 
     5     var efHost = (EfTextTemplateHost)Host;
     6     var code = new CodeGenerationTools(this);
     7     
     8 #>
     9 //------------------------------------------------------------------------------
    10 // <auto-generated>
    11 //     此代码由工具生成。
    12 //     对此文件的更改可能会导致不正确的行为,并且如果
    13 //     重新生成代码,这些更改将会丢失。
    14 // </auto-generated>
    15 // <copyright file="<#= efHost.EntityContainer.Name #>.cs">
    16 //        Copyright(c)2015  rights reserved.
    17 //        CLR版本:4.0.30319.239
    18 //        开发组织:李文学@上海同岩土木科技工程有限公司
    19 //        所属工程:TY.*
    20 //        生成时间:<#= DateTime.Now.ToString("yyyy-MM-dd HH:mm") #>
    21 // </copyright>
    22 //------------------------------------------------------------------------------
    23 
    24 using System.Data.Entity;
    25 using System.Data.Entity.Infrastructure;
    26 using <#= code.EscapeNamespace(efHost.MappingNamespace) #>;
    27 
    28 namespace <#= code.EscapeNamespace(efHost.Namespace) #>
    29 {
    30     public partial class <#= efHost.EntityContainer.Name #> : DbContext
    31     {
    32         static <#= efHost.EntityContainer.Name #>()
    33         {
    34             Database.SetInitializer<<#= efHost.EntityContainer.Name #>>(null);
    35         }
    36 
    37         public <#= efHost.EntityContainer.Name #>()
    38             : base("Name=<#= efHost.EntityContainer.Name #>")
    39         {
    40         }
    41 
    42 <#
    43     var summary="";
    44     foreach (var set in efHost.EntityContainer.BaseEntitySets.OfType<EntitySet>())
    45     {
    46         if(set.Documentation !=null && set.Documentation.Summary!=null)
    47             summary=set.Documentation.Summary;
    48 
    49         else if(set.Documentation !=null && set.Documentation.LongDescription!=null)
    50             summary=set.Documentation.LongDescription;
    51         else
    52             summary=string.Format("[{0}]", set.ElementType.Name);
    53 #>
    54         /// <summary>
    55         /// <#= summary #>
    56         /// </summary>
    57         public DbSet<<#= set.ElementType.Name #>> <#= set.Name #> { get; set; }
    58 <#
    59     }
    60 #>
    61 
    62         protected override void OnModelCreating(DbModelBuilder modelBuilder)
    63         {
    64 <#
    65     foreach (var set in efHost.EntityContainer.BaseEntitySets.OfType<EntitySet>())
    66     {
    67 #>
    68             modelBuilder.Configurations.Add(new <#= set.ElementType.Name #>Map());
    69 <#
    70     }
    71 #>
    72         }
    73     }
    74 }

     

  • Entity.tt
  •   1 <#@ template hostspecific="true" language="C#" #>
      2 <#@ include file="EF.Utility.CS.ttinclude" #><#@
      3  output extension=".cs" encoding="UTF-8" #><#
      4 
      5     var efHost = (EfTextTemplateHost)Host;
      6     var code = new CodeGenerationTools(this);
      7     
      8 #>
      9 //------------------------------------------------------------------------------
     10 // <auto-generated>
     11 //     此代码由工具生成。
     12 //     对此文件的更改可能会导致不正确的行为,并且如果
     13 //     重新生成代码,这些更改将会丢失。
     14 // </auto-generated>
     15 // <copyright file="<#=        efHost.EntityType.Name #>.cs">
     16 //        Copyright(c)2015   rights reserved.
     17 //        CLR版本:4.0.30319.239
     18 //        开发组织:李文学@上海同岩土木科技工程有限公司
     19 //        所属工程:TY.*
     20 //        生成时间:<#=        DateTime.Now.ToString("yyyy-MM-dd HH:mm") #>
     21 // </copyright>
     22 //------------------------------------------------------------------------------
     23 
     24 using System;
     25 using System.Collections.Generic;
     26 using XXXX.EF;
     27 using XXXX.EF.Base;
     28 using XXXX.ToolT4;
     29 
     30 <#
     31     var summary="";
     32     var entity=efHost.EntityType;
     33     if(entity.Documentation !=null && entity.Documentation.Summary!=null)
     34         summary=entity.Documentation.Summary;
     35 
     36     else if(entity.Documentation !=null && entity.Documentation.LongDescription!=null)
     37         summary=entity.Documentation.LongDescription;
     38     else
     39         summary=string.Format("[{0}]", entity.Name);
     40 
     41 #>
     42 
     43 namespace <#=        code.EscapeNamespace(efHost.Namespace) #>
     44 {
     45     /// <summary>
     46     /// <#=        summary#>
     47     /// </summary>
     48     [Serializable]
     49     public partial class <#=        efHost.EntityType.Name #> : BaseEntity
     50     {
     51 <#
     52     var collectionNavigations = efHost.EntityType.NavigationProperties.Where(
     53         np => np.DeclaringType == efHost.EntityType
     54         && np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many);
     55 
     56     // Add a ctor to initialize any collections
     57     if (collectionNavigations.Any())
     58     {
     59 #>
     60         /// <summary>
     61         /// 构造函数
     62         /// </summary>
     63         public <#=            code.Escape(efHost.EntityType) #>()
     64         {
     65 <#
     66         foreach (var navProperty in collectionNavigations)
     67         {
     68 #>
     69             this.<#=                code.Escape(navProperty) #> = new List<<#=                code.Escape(navProperty.ToEndMember.GetEntityType()) #>>();
     70 <#
     71         }
     72 #>
     73         }
     74 
     75 <#
     76     }
     77         
     78     foreach (var property in efHost.EntityType.Properties)
     79     {
     80         var typeUsage = code.Escape(property.TypeUsage);
     81 
     82         // Fix-up spatial types for EF6
     83         if (efHost.EntityFrameworkVersion >= new Version(6, 0)
     84             && typeUsage.StartsWith("System.Data.Spatial."))
     85         {
     86             typeUsage = typeUsage.Replace(
     87                 "System.Data.Spatial.",
     88                 "System.Data.Entity.Spatial.");
     89         }
     90         if(property.Documentation !=null && property.Documentation.Summary!=null)
     91             summary=property.Documentation.Summary;
     92 
     93         else  if(property.Documentation !=null && property.Documentation.LongDescription!=null)
     94             summary=property.Documentation.LongDescription;
     95         else   
     96             summary=string.Format("[{0}]", property.Name);
     97 
     98 #>
     99         /// <summary>
    100         /// <#=            summary#>
    101         /// </summary>
    102         <#=            Accessibility.ForProperty(property) #> <#=            typeUsage #> <#=            code.Escape(property) #> { get; set; }
    103 <#
    104     }
    105 
    106     foreach (var navProperty in efHost.EntityType.NavigationProperties.Where(np => np.DeclaringType == efHost.EntityType))
    107     {
    108         if (navProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
    109         {
    110 #>
    111         /// <summary>
    112         /// 导航集合:<#=                navProperty#>
    113         /// </summary>
    114         public virtual ICollection<<#=                code.Escape(navProperty.ToEndMember.GetEntityType()) #>> <#=                code.Escape(navProperty) #> { get; set; }
    115 <#
    116         }
    117         else
    118         {
    119 #>
    120         /// <summary>
    121         /// 导航属性:<#=                navProperty#>
    122         /// </summary>
    123         public virtual <#=                code.Escape(navProperty.ToEndMember.GetEntityType()) #> <#=                code.Escape(navProperty) #> { get; set; }
    124 <#
    125         }
    126     }
    127 #>
    128     }
    129 }

     

  • Mapping.tt
  • <#@ template hostspecific="true" language="C#" #>
    <#@ include file="EF.Utility.CS.ttinclude" #><#@
     output extension=".cs" encoding="UTF-8" #><#
    
        var efHost = (EfTextTemplateHost)Host;
        var code = new CodeGenerationTools(this);
        #>
        
    //------------------------------------------------------------------------------
    // <auto-generated>
    //     此代码由工具生成。
    //     对此文件的更改可能会导致不正确的行为,并且如果
    //     重新生成代码,这些更改将会丢失。
    // </auto-generated>
    // <copyright file="<#= efHost.EntityType.Name #>Map.cs">
    //        Copyright(c)2015   rights reserved.
    //        CLR版本:4.0.30319.239
    //        开发组织:李文学@上海同岩土木科技工程有限公司
    //        所属工程:TY.*
    //        生成时间:<#= DateTime.Now.ToString("yyyy-MM-dd HH:mm") #>
    // </copyright>
    //------------------------------------------------------------------------------
    
        <#
        if (efHost.EntityFrameworkVersion >= new Version(4, 4))
        {
    #>
    using System.ComponentModel.DataAnnotations.Schema;
    <#
        }
        else
        {
    #>
    using System.ComponentModel.DataAnnotations;
    <#
        }
    #>
    using System.Data.Entity.ModelConfiguration;
    
    namespace <#= code.EscapeNamespace(efHost.Namespace) #>
    {
        public class <#= efHost.EntityType.Name #>Map : EntityTypeConfiguration<<#= efHost.EntityType.Name #>>
        {
            public <#= efHost.EntityType.Name #>Map()
            {
                // Primary Key
    <#
        if (efHost.EntityType.KeyMembers.Count() == 1)
        {
    #>
                this.HasKey(t => t.<#= efHost.EntityType.KeyMembers.Single().Name #>);
    <#
        }
        else
        {
    #>
                this.HasKey(t => new { <#= string.Join(", ", efHost.EntityType.KeyMembers.Select(m => "t." + m.Name)) #> });
    <#
        }
    #>
    
                // Properties
    <#
        foreach (var prop in efHost.EntityType.Properties)
        {
            var type = (PrimitiveType)prop.TypeUsage.EdmType;
            var isKey = efHost.EntityType.KeyMembers.Contains(prop);
            var storeProp = efHost.PropertyToColumnMappings[prop];
            var sgpFacet = storeProp.TypeUsage.Facets.SingleOrDefault(f => f.Name == "StoreGeneratedPattern");
            var storeGeneratedPattern = sgpFacet == null
                ? StoreGeneratedPattern.None
                : (StoreGeneratedPattern)sgpFacet.Value;
                
            var configLines = new List<string>();
                 
            if (type.ClrEquivalentType == typeof(int)
                || type.ClrEquivalentType == typeof(decimal)
                || type.ClrEquivalentType == typeof(short)
                || type.ClrEquivalentType == typeof(long))
            {
                if (isKey && storeGeneratedPattern != StoreGeneratedPattern.Identity)
                {
                    configLines.Add(".HasDatabaseGeneratedOption(DatabaseGeneratedOption.None)");
                }
                else if ((!isKey || efHost.EntityType.KeyMembers.Count > 1) && storeGeneratedPattern == StoreGeneratedPattern.Identity)
                {
                    configLines.Add(".HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)");
                }
            }
                        
            if (type.ClrEquivalentType == typeof(string)
                || type.ClrEquivalentType == typeof(byte[]))
            {
                if (!prop.Nullable)
                {
                    configLines.Add(".IsRequired()");
                }
                    
                var unicodeFacet = (Facet)prop.TypeUsage.Facets.SingleOrDefault(f => f.Name == "IsUnicode");
                if(unicodeFacet != null && !(bool)unicodeFacet.Value)
                {
                    configLines.Add(".IsUnicode(false)");
                }
                    
                var fixedLengthFacet = (Facet)prop.TypeUsage.Facets.SingleOrDefault(f => f.Name == "FixedLength");
                if (fixedLengthFacet != null && (bool)fixedLengthFacet.Value)
                {
                    configLines.Add(".IsFixedLength()");
                }
                    
                var maxLengthFacet = (Facet)prop.TypeUsage.Facets.SingleOrDefault(f => f.Name == "MaxLength");
                if (maxLengthFacet != null && !maxLengthFacet.IsUnbounded)
                {
                    configLines.Add(string.Format(".HasMaxLength({0})", maxLengthFacet.Value));
    
                    if (storeGeneratedPattern == StoreGeneratedPattern.Computed
                        && type.ClrEquivalentType == typeof(byte[])
                        && (int)maxLengthFacet.Value == 8)
                    {
                        configLines.Add(".IsRowVersion()");
                    }
                }
            }
                
            if(configLines.Any())
            {
    #>
                this.Property(t => t.<#= prop.Name #>)
                    <#= string.Join("\r\n                ", configLines) #>;
    
    <#
            }
        }
    
        var tableSet = efHost.TableSet;
        var tableName = (string)tableSet.MetadataProperties["Table"].Value
            ?? tableSet.Name;
        var schemaName = (string)tableSet.MetadataProperties["Schema"].Value;
    #>
                // Table & Column Mappings
                this.ToTable("<#= tableName #>");
    <#  
        foreach (var property in efHost.EntityType.Properties)
        {
            if(property.TypeUsage.EdmType is PrimitiveType && ((PrimitiveType)property.TypeUsage.EdmType).PrimitiveTypeKind == PrimitiveTypeKind.Decimal)
            {
                var jdLen = property.TypeUsage.Facets[2].Value;
                var jdXsv = property.TypeUsage.Facets[3].Value;
    #>
                this.Property(t => t.<#=property.Name #>).HasColumnName("<#=efHost.PropertyToColumnMappings[property].Name #>").HasPrecision(<#=jdLen#>,<#=jdXsv#>);
    <#
            }
            else{
    #>
                this.Property(t => t.<#=property.Name #>).HasColumnName("<#=efHost.PropertyToColumnMappings[property].Name #>");
    <#
            }
        }
            
        // Find m:m relationshipsto configure 
        var manyManyRelationships = efHost.EntityType.NavigationProperties
            .Where(np => np.DeclaringType == efHost.EntityType
                && np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many
                && np.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many
                && np.RelationshipType.RelationshipEndMembers.First() == np.FromEndMember); // <- ensures we only configure from one end
            
        // Find FK relationships that this entity is the dependent of
        var fkRelationships = efHost.EntityType.NavigationProperties
            .Where(np => np.DeclaringType == efHost.EntityType
                && ((AssociationType)np.RelationshipType).IsForeignKey
                && ((AssociationType)np.RelationshipType).ReferentialConstraints.Single().ToRole == np.FromEndMember);
            
        if(manyManyRelationships.Any() || fkRelationships.Any())
        {
    #>
    
                // Relationships
    <#
            foreach (var navProperty in manyManyRelationships)
            {
                var otherNavProperty = navProperty.ToEndMember.GetEntityType().NavigationProperties.Where(n => n.RelationshipType == navProperty.RelationshipType && n != navProperty).Single();
                var association = (AssociationType)navProperty.RelationshipType;
                var mapping = efHost.ManyToManyMappings[association];
                var item1 = mapping.Item1;
                var mappingTableName = (string)mapping.Item1.MetadataProperties["Table"].Value
                    ?? item1.Name;
                var mappingSchemaName = (string)item1.MetadataProperties["Schema"].Value;
    
                // Need to ensure that FKs are decalred in the same order as the PK properties on each principal type
                var leftType = (EntityType)navProperty.DeclaringType;
                var leftKeyMappings = mapping.Item2[navProperty.FromEndMember];
                var leftColumns = string.Join(", ", leftType.KeyMembers.Select(m => "\"" + leftKeyMappings[m] + "\""));
                var rightType = (EntityType)otherNavProperty.DeclaringType;
                var rightKeyMappings = mapping.Item2[otherNavProperty.FromEndMember];
                var rightColumns = string.Join(", ", rightType.KeyMembers.Select(m => "\"" + rightKeyMappings[m] + "\""));
    #>
                this.HasMany(t => t.<#= code.Escape(navProperty) #>)
                    .WithMany(t => t.<#= code.Escape(otherNavProperty) #>)
                    .Map(m =>
                        {
                            m.ToTable("<#= mappingTableName #>");
                            m.MapLeftKey(<#= leftColumns #>);
                            m.MapRightKey(<#= rightColumns #>);
                        });
    
    <#
            }
                
            foreach (var navProperty in fkRelationships)
            {
                var otherNavProperty = navProperty.ToEndMember.GetEntityType().NavigationProperties.Where(n => n.RelationshipType == navProperty.RelationshipType && n != navProperty).Single();
                var association = (AssociationType)navProperty.RelationshipType;
                    
                if (navProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.One)
                {
    #>
                this.HasRequired(t => t.<#= code.Escape(navProperty) #>)
    <#
                }
                else
                {
    #>
                this.HasOptional(t => t.<#= code.Escape(navProperty) #>)
    <#
                }
                    
                if(navProperty.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
                {
    #>
                    .WithMany(t => t.<#= code.Escape(otherNavProperty) #>)
    <#
                    if(association.ReferentialConstraints.Single().ToProperties.Count == 1)
                    {
    #>
                    .HasForeignKey(d => d.<#= association.ReferentialConstraints.Single().ToProperties.Single().Name #>);
    <#
                    }
                    else
                    {
    #>
                    .HasForeignKey(d => new { <#= string.Join(", ", association.ReferentialConstraints.Single().ToProperties.Select(p => "d." + p.Name)) #> });
    <#
                    }
                }
                else
                {
                    // NOTE: We can assume that this is a required:optional relationship 
                    //       as EDMGen will never create an optional:optional relationship
                    //          because everything is one:many except PK-PK relationships which must be required
    #>
                    .WithOptional(t => t.<#= code.Escape(otherNavProperty) #>);
    <#    
                    }
                }
    #>
    
    <#
            }
    #>
            }
        }
    }

     

 

  • BaseEntity.cs
  • using System;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    
    namespace XXXX.EF.Base
    {
        /// <summary>
        /// 抽象实体类型:可用作DbFirst使用以作为Entiry基类
        /// </summary>
        public abstract class BaseEntity
        {
        }
    }

     

  • T4ModelInfo.cs
  • using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Reflection;
    
    namespace XXXX.ToolT4
    {
        /// <summary>
        /// T4实体模型信息类
        /// </summary>
        public class T4ModelInfo
        {
            /// <summary>
            /// 获取 模型所在模块名称
            /// </summary>
            public string ModuleName { get; private set; }
    
            /// <summary>
            /// 获取 模型名称
            /// </summary>
            public string Name { get; private set; }
    
            /// <summary>
            /// 获取 模型描述
            /// </summary>
            public string Description { get; private set; }
    
            /// <summary>
            /// 属性集合
            /// </summary>
            public IEnumerable<PropertyInfo> Properties { get; private set; }
    
            public T4ModelInfo(Type modelType)
            {
                var @namespace = modelType.Namespace;
                if (@namespace == null)
                {
                    return;
                }
                var index = @namespace.LastIndexOf(.) + 1;
                ModuleName = @namespace.Substring(index, @namespace.Length - index);
                Name = modelType.Name;
                var descAttributes = modelType.GetCustomAttributes(typeof(DescriptionAttribute), true);
                Description = descAttributes.Length == 1 ? ((DescriptionAttribute)descAttributes[0]).Description : Name;
                Properties = modelType.GetProperties();
            }
        }
    }

     

有了上传代码借助于EntityReverseCode就可以生成我们需要的实体类,实体映射类

 

以上是关于ReverseEngineerCodeFirst 自定义模板的主要内容,如果未能解决你的问题,请参考以下文章