zoukankan      html  css  js  c++  java
  • [原创]EF架构随心所欲打造属于你自己的DbModel

    前言

       我们都知道EF可以生成Dbmodel,系统生成的Model有时候并不是我们想要的,如何我们要生成自己的Model,那么久需要我们手动的去修改T4模版,T4是对“Text Template Transformation Toolkit”(4个T)的简称。如果你对T4不怎么了解可以去看蒋金楠(Artech)文章从数据到代码——基于T4的代码生成方式

    1.0先看看我们要达到的效果图吧

     2.0首先我们来修改T4模版吧

       打开T4模版,找到代码 WriteHeader(codeStringGenerator, fileManager);

    我们首先定义变量(图中黄色代码为我们自己添加的代码)

    WriteHeader(codeStringGenerator, fileManager);
    string summary=string.Empty; 定义变量
    foreach (var entity in typeMapper.GetItemsToGenerate<EntityType>(itemCollection))
    {
        fileManager.StartNewFile(entity.Name + ".cs");
        BeginNamespace(code);
           if(entity.Documentation !=null && entity.Documentation.Summary!=null)
                summary=entity.Documentation.Summary;
            else
                summary=entity.Name;
    #>
    <#=codeStringGenerator.UsingDirectives(inHeader: false)#>
    using System.ComponentModel.DataAnnotations; 导入你需要的命名空间
    
    /// <summary>
    /// <#=            summary#>给类加注释
    /// </summary>
    [Serializable]
    <#=codeStringGenerator.EntityClassOpening(entity)#>

    看看效果图如下:

    类上面的注释已经加好了,接下来就是删除构造函数,删除以下代码即可:

        public <#=code.Escape(entity)#>()
        {
    <#
            foreach (var edmProperty in propertiesWithDefaultValues)
            {
    #>
            this.<#=code.Escape(edmProperty)#> = <#=typeMapper.CreateLiteral(edmProperty.DefaultValue)#>;
    <#
            }
    
            foreach (var navigationProperty in collectionNavigationProperties)
            {
    #>
            this.<#=code.Escape(navigationProperty)#> = new HashSet<<#=typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType())#>>();
    <#
            }
    
            foreach (var complexProperty in complexProperties)
            {
    #>
            this.<#=code.Escape(complexProperty)#> = new <#=typeMapper.GetTypeName(complexProperty.TypeUsage)#>();
    <#
            }
    #>
        }

     接下来我们把这些可空类型还原成本来面目,已经去掉virtual关键字,修改代码如下:

    public string GetTypeName(EdmType edmType, bool? isNullable, string modelNamespace)
        {
            if (edmType == null)
            {
                return null;
            }
    
            var collectionType = edmType as CollectionType;
            if (collectionType != null)
            {
                return String.Format(CultureInfo.InvariantCulture, "ICollection<{0}>", GetTypeName(collectionType.TypeUsage, modelNamespace));
            }
    
            var typeName = _code.Escape(edmType.MetadataProperties
                                    .Where(p => p.Name == ExternalTypeNameAttributeName)
                                    .Select(p => (string)p.Value)
                                    .FirstOrDefault())
                ?? (modelNamespace != null && edmType.NamespaceName != modelNamespace ?
                    _code.CreateFullName(_code.EscapeNamespace(edmType.NamespaceName), _code.Escape(edmType)) :
                    _code.Escape(edmType));
    
            if (edmType is StructuralType)
            {
                return typeName;
            }
    
            if (edmType is SimpleType)
            {
                var clrType = UnderlyingClrType(edmType);
                if (!IsEnumType(edmType))
                {
                    typeName = _code.Escape(clrType);
                }
    
                typeName = FixNamespaces(typeName);
    
                return clrType.IsValueType && isNullable == true ?
                   // String.Format(CultureInfo.InvariantCulture, "Nullable<{0}>", typeName) :原来的代码
    String.Format(CultureInfo.InvariantCulture, "{0}?", typeName) :自己修改的代码
    typeName; }
    throw new ArgumentException("edmType"); }
       public string NavigationProperty(NavigationProperty navigationProperty)
        {
            var endType = _typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType());
            return string.Format(
                CultureInfo.InvariantCulture,
                "public {1} {2} {{ {3}get; {4}set; }}",
                AccessibilityAndVirtual(Accessibility.ForProperty(navigationProperty)),
                navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? ("ICollection<" + endType + ">") : endType,
                _code.Escape(navigationProperty),
                _code.SpaceAfter(Accessibility.ForGetter(navigationProperty)),
                _code.SpaceAfter(Accessibility.ForSetter(navigationProperty)));
        }

    接下来来给属性上添加注释:(橙色代码删除,皇色代码添加)

    /// <summary>
    /// <#=            summary#>
    /// </summary>
    [Serializable]
    <#=codeStringGenerator.EntityClassOpening(entity)#>
    {
    <#
        var propertiesWithDefaultValues = typeMapper.GetPropertiesWithDefaultValues(entity);
        var collectionNavigationProperties = typeMapper.GetCollectionNavigationProperties(entity);
        var complexProperties = typeMapper.GetComplexProperties(entity);
    
        if (propertiesWithDefaultValues.Any() || collectionNavigationProperties.Any() || complexProperties.Any())
        {
    #>
    
    
    <#
        }删除掉代码
    
        var simpleProperties = typeMapper.GetSimpleProperties(entity);
        if (simpleProperties.Any())
        {
            foreach (var edmProperty in simpleProperties)
            {
    
                    if (edmProperty.Documentation != null && edmProperty.Documentation.Summary != null)
                    {
                        if(!entity.KeyMembers.Contains(edmProperty.Name))
                            summary=edmProperty.Documentation.Summary.ToLower().Replace("id","名称");
                        else
                            summary=edmProperty.Documentation.Summary;
                    }
                    else
                    {
                        summary="";
                    }
    
    
    #>
    
    <#                //if(edmProperty.Name.ToLower() == "id")
                    // continue;var a=edmProperty.Nullable;
                    
                    var keyName=""; 
                    if(entity.KeyMembers.Contains(edmProperty.Name))          
                        keyName="[Key]";
                    var required="";
                    if(!edmProperty.Nullable)
                        required="[Required(ErrorMessage = "请输入{0}")]";
                    string facetName = "MaxLength";
                    var lengthDes="";
                    var stringLengthDes="";
                    int maxLength = 0; 
                    if (code.Escape(edmProperty.TypeUsage).ToLower().Contains("string") && Int32.TryParse(edmProperty.TypeUsage.Facets[facetName].Value.ToString(), out maxLength)){
                        lengthDes="[MaxLength("+maxLength+")]";
                        stringLengthDes="[StringLength("+maxLength+")]";
                    }
                    var dataType="";
                    if (code.Escape(edmProperty.TypeUsage).ToLower().Contains("datetime"))
                        dataType="[DataType(DataType.DateTime)]";
                    else if (edmProperty.Name.ToLower().Contains("password"))
                        dataType="[DataType(DataType.Password)]";
      
        #>
        /// <summary>
        /// <#=                    summary#>
        /// </summary>
    <#                if(!string.IsNullOrWhiteSpace(required)){ #>
        <#=                        required #>
    <#                    } if(!string.IsNullOrWhiteSpace(summary)){ #>
        <#=                        "[Display(Name = ""+summary+"")]" #>
    <#                    } if(!string.IsNullOrWhiteSpace(lengthDes)){ #>
        <#=                        lengthDes #>
    <#                    } if(!string.IsNullOrWhiteSpace(stringLengthDes)){ #>
        <#=                        stringLengthDes #>
    <#                    } if(!string.IsNullOrWhiteSpace(dataType)){ #>
        <#=                        dataType #>
    <#                    } if(!string.IsNullOrWhiteSpace(keyName)){ #>
        <#=                        keyName #>
    <#                } #>
        <#=codeStringGenerator.Property(edmProperty)#>

     

    效果基本已经差不多,可是这里为什么没有注释,园子里已经有其他文章来处理这个问题:

    1.0EF架构~将数据库注释添加导入到模型实体类中 2.0entity framework框架生成摘要文档为空(没有元数据文档可用)的bug解决方案

    按照步骤做了,可是问题还是没有解决,怎么办,其实根本原因是:

    主要原因是这里的摘要没有数据。不断的尝试啊,entity framework框架生成摘要文档为空(没有元数据文档可用)的bug解决方案 试了几次还是没有从根本上解决问题,怎么办了...

    3.0解决bug

     没办法我们查看EFTSQLDocumentation.Generator的源码终于找到问题所在

            public String ConnectionString { get; set; }
            public String InputFileName { get; set; }
            public String OutputFileName { get; set; }
    
            private SqlConnection _connection;
    
    
            public Program(String connectionString, String inputFileName, String outputFileName)
            {
                this.ConnectionString = connectionString;
                this.InputFileName = inputFileName;
                this.OutputFileName = outputFileName;
    
                this._connection = new SqlConnection(connectionString);
                this._connection.Open();
            }
            public void Dispose()
            {
                this._connection.Dispose();
            }
    
            private void CreateDocumentation()
            {
    
                XDocument doc = XDocument.Load(this.InputFileName);
                IEnumerable<XElement> entityTypeElements = doc.Descendants("{http://schemas.microsoft.com/ado/2008/09/edm}EntityType");
    
                int i = 0;
                foreach (XElement entityTypeElement in entityTypeElements)
                {
                    String tableName = entityTypeElement.Attribute("Name").Value;
                    IEnumerable<XElement> propertyElements = entityTypeElement.Descendants("{http://schemas.microsoft.com/ado/2008/09/edm}Property");
    
                    Console.Clear();
                    Console.WriteLine("Analyzing table {0} of {1}", i++, entityTypeElements.Count());
                    Console.WriteLine(" => TableName : {0}" +
                                      "
     => property count : {1}", tableName, propertyElements.Count());
    
                    this.AddNodeDocumentation(entityTypeElement, GetTableDocumentation(tableName));
    
                    foreach (XElement propertyElement in propertyElements)
                    {
                        String columnName = propertyElement.Attribute("Name").Value;
                        this.AddNodeDocumentation(propertyElement, GetColumnDocumentation(tableName, columnName));
                    }
                }
    
                Console.WriteLine("Writing result to {0}", this.OutputFileName);
                if (File.Exists(this.OutputFileName))
                    File.Delete(this.OutputFileName);
                doc.Save(this.OutputFileName);
            }
            private void AddNodeDocumentation(XElement element, String documentation)
            {
                if (String.IsNullOrEmpty(documentation))
                    return;
                element.Descendants("{http://schemas.microsoft.com/ado/2008/09/edm}Documentation").Remove();
    
                element.AddFirst(new XElement("{http://schemas.microsoft.com/ado/2008/09/edm}Documentation", new XElement("{http://schemas.microsoft.com/ado/2008/09/edm}Summary", documentation)));
            }
            private String GetTableDocumentation(String tableName)
            {
                using (SqlCommand command = new SqlCommand(@" SELECT [value] 
                                                              FROM fn_listextendedproperty (
                                                                    'MS_Description', 
                                                                    'schema', 'dbo', 
                                                                    'table',  @TableName, 
                                                                    null, null)", this._connection))
                {
    
                    command.Parameters.AddWithValue("TableName", tableName);
    
                    return command.ExecuteScalar() as String;
                }
            }
            private String GetColumnDocumentation(String tableName, String columnName)
            {
                using (SqlCommand command = new SqlCommand(@"SELECT [value] 
                                                             FROM fn_listextendedproperty (
                                                                    'MS_Description', 
                                                                    'schema', 'dbo', 
                                                                    'table', @TableName, 
                                                                    'column', @columnName)", this._connection))
                {
    
                    command.Parameters.AddWithValue("TableName", tableName);
                    command.Parameters.AddWithValue("ColumnName", columnName);
    
                    return command.ExecuteScalar() as String;
                }
            }

    我们的edmx中的代码如下:

          <Schema Namespace="yaochufaNewTestModel.Store" Provider="System.Data.SqlClient" ProviderManifestToken="2008" Alias="Self" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns:customannotation="http://schemas.microsoft.com/ado/2013/11/edm/customannotation" xmlns="http://schemas.microsoft.com/ado/2009/11/edm/ssdl">
            <EntityType Name="Activities">
              <Key>
                <PropertyRef Name="ActivityId" />
              </Key>
              <Property Name="ActivityId" Type="int" StoreGeneratedPattern="Identity" Nullable="false" />
              <Property Name="ActivityType" Type="int" Nullable="false" />
              <Property Name="ProvinceId" Type="int" />
              <Property Name="CityId" Type="int" />
              <Property Name="Description" Type="nvarchar" MaxLength="50" />
              <Property Name="IsActive" Type="bit" Nullable="false" />
              <Property Name="EndDate" Type="datetime" />
              <Property Name="StartDate" Type="datetime" />
              <Property Name="DrawDate" Type="datetime" />
              <Property Name="DrawInfo" Type="nvarchar" MaxLength="1000" />
              <Property Name="LimitTime" Type="int" />
              <Property Name="ShowStartDate" Type="datetime" />
              <Property Name="ShowEndDate" Type="datetime" />
              <Property Name="PrizeCount" Type="int" />
              <Property Name="ModifiedById" Type="int" />
              <Property Name="ModifiedByName" Type="nvarchar" MaxLength="50" />
              <Property Name="ModifiedDate" Type="datetime" />
              <Property Name="CreatedById" Type="int" Nullable="false" />
              <Property Name="CreatedByName" Type="nvarchar" MaxLength="50" Nullable="false" />
              <Property Name="CreatedDate" Type="datetime" Nullable="false" />
            </EntityType>

    需要修改的就是EFTSQLDocumentation.Generator源码中的xml命名空间我们要替换成 http://schemas.microsoft.com/ado/2009/11/edm最终在cmd中运行如下代码:

    EFTSQLDocumentation.Generator.exe -c "data source=.;initial catalog=yaochufaNewTest;user id=sa;password=123;" -i " D:Feng.TestFeng.TestModel1.edmx"

    得到效果图如下:

  • 相关阅读:
    thinkphp3.2生成二维码
    php实现图片下载
    yii2.0 Activeform表单部分组件使用方法
    Yii2美化confirm
    Yii2学习笔记之场景
    tp5页面输出时,搜索后跳转下一页的处理
    php页面输出时,js设置input框的选中值
    mac中使用rz,sz上传文件
    golang的命令行程序开发
    Sring MVC基于Java Config方式配置Mybatis, 无XML
  • 原文地址:https://www.cnblogs.com/fenglingyi/p/4320757.html
Copyright © 2011-2022 走看看