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.23920 
    18 // 生成时间:<#= 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 
    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
    // 生成时间:<#= 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就可以生成我们需要的实体类,实体映射类

 

posted @ 2018-01-19 09:35  李文学  阅读(544)  评论(4编辑  收藏  举报