[原创]EF架构随心所欲打造属于你自己的DbModel

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: |||超大  

前言 我们都知道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);stringsummary=string.Empty;定义变量foreach(varentityintypeMapper.GetItemsToGenerate<EntityType>(itemCollection))

{

fileManager.StartNewFile(entity.Name+".cs");

BeginNamespace(code);if(entity.Documentation !=null&& entity.Documentation.Summary!=null)

summary=entity.Documentation.Summary;elsesummary=entity.Name;#>

<#=codeStringGenerator.UsingDirectives(inHeader:false)#>usingSystem.ComponentModel.DataAnnotations;导入你需要的命名空间///<summary>///<#= summary#>给类加注释///</summary>[Serializable]<#=codeStringGenerator.EntityClassOpening(entity)#>

看看效果图如下:

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

public<#=code.Escape(entity)#>()

{<#foreach(varedmPRopertyinpropertiesWithDefaultValues)

{

#>this.<#=code.Escape(edmProperty)#> = <#=typeMapper.CreateLiteral(edmProperty.DefaultValue)#>;<#

}foreach(varnavigationPropertyincollectionNavigationProperties)

{

#>this.<#=code.Escape(navigationProperty)#> =newHashSet<<#=typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType())#>>();<#

}foreach(varcomplexPropertyincomplexProperties)

{

#>this.<#=code.Escape(complexProperty)#> =new<#=typeMapper.GetTypeName(complexProperty.TypeUsage)#>();<#

}

#>}

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

publicstringGetTypeName(EdmType edmType,bool? isNullable,stringmodelNamespace)

{if(edmType ==null)

{returnnull;

}varcollectionType = edmTypeasCollectionType;if(collectionType !=null)

{returnString.Format(CultureInfo.InvariantCulture,"ICollection<{0}>", GetTypeName(collectionType.TypeUsage, modelNamespace));

}vartypeName =_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(edmTypeisStructuralType)

{returntypeName;

}if(edmTypeisSimpleType)

{varclrType =UnderlyingClrType(edmType);if(!IsEnumType(edmType))

{

typeName=_code.Escape(clrType);

}

typeName=FixNamespaces(typeName);returnclrType.IsValueType && isNullable ==true?// String.Format(CultureInfo.InvariantCulture,"Nullable<{0}>", typeName) :原来的代码

String.Format(CultureInfo.InvariantCulture, "{0}?", typeName) :自己修改的代码

typeName;

}thrownewArgumentException("edmType");

}

publicstringNavigationProperty(NavigationProperty navigationProperty)

{varendType =_typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType());returnstring.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)#>{<#varpropertiesWithDefaultValues =typeMapper.GetPropertiesWithDefaultValues(entity);varcollectionNavigationProperties =typeMapper.GetCollectionNavigationProperties(entity);varcomplexProperties =typeMapper.GetComplexProperties(entity);if(propertiesWithDefaultValues.Any() || collectionNavigationProperties.Any() ||complexProperties.Any())

{

#>

<#

}删除掉代码varsimpleProperties =typeMapper.GetSimpleProperties(entity);if(simpleProperties.Any())

{foreach(varedmPropertyinsimpleProperties)

{if(edmProperty.Documentation !=null&& edmProperty.Documentation.Summary !=null)

{if(!entity.KeyMembers.Contains(edmProperty.Name))

summary=edmProperty.Documentation.Summary.ToLower().Replace("id","名称");elsesummary=edmProperty.Documentation.Summary;

}else{

summary="";

}#><#//if(edmProperty.Name.ToLower() == "id")//continue;var a=edmProperty.Nullable;varkeyName="";if(entity.KeyMembers.Contains(edmProperty.Name))

keyName="[Key]";varrequired="";if(!edmProperty.Nullable)

required="[Required(ErrorMessage = \"请输入{0}\")]";stringfacetName ="MaxLength";varlengthDes="";varstringLengthDes="";intmaxLength =0;if(code.Escape(edmProperty.TypeUsage).ToLower().Contains("string") && Int32.TryParse(edmProperty.TypeUsage.Facets[facetName].Value.ToString(),outmaxLength)){

lengthDes="[MaxLength("+maxLength+")]";

stringLengthDes="[StringLength("+maxLength+")]";

}vardataType="";if(code.Escape(edmProperty.TypeUsage).ToLower().Contains("datetime"))

dataType="[DataType(DataType.DateTime)]";elseif(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的源码终于找到问题所在

publicString ConnectionString {get;set; }publicString InputFileName {get;set; }publicString OutputFileName {get;set; }privateSqlConnection _connection;publicProgram(String connectionString, String inputFileName, String outputFileName)

{this.ConnectionString =connectionString;this.InputFileName =inputFileName;this.OutputFileName =outputFileName;this._connection =newSqlConnection(connectionString);this._connection.Open();

}publicvoidDispose()

{this._connection.Dispose();

}privatevoidCreateDocumentation()

{

XDocument doc= XDocument.Load(this.InputFileName);

IEnumerable<XElement> entityTypeElements = doc.Descendants("{http://schemas.microsoft.com/ado/2008/09/edm}EntityType");inti =0;foreach(XElement entityTypeElementinentityTypeElements)

{

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}"+"\n => property count : {1}", tableName, propertyElements.Count());this.AddNodeDocumentation(entityTypeElement, GetTableDocumentation(tableName));foreach(XElement propertyElementinpropertyElements)

{

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);

}privatevoidAddNodeDocumentation(XElement element, String documentation)

{if(String.IsNullOrEmpty(documentation))return;

element.Descendants("{http://schemas.microsoft.com/ado/2008/09/edm}Documentation").Remove();

element.AddFirst(newXElement("{http://schemas.microsoft.com/ado/2008/09/edm}Documentation",newXElement("{http://schemas.microsoft.com/ado/2008/09/edm}Summary", documentation)));

}privateString GetTableDocumentation(String tableName)

{using(SqlCommand command =newSqlCommand(@"SELECT [value]

FROM fn_listextendedproperty (

'MS_Description',

'schema', 'dbo',

'table', @TableName,

null, null)",this._connection))

{

command.Parameters.AddWithValue("TableName", tableName);returncommand.ExecuteScalar()asString;

}

}privateString GetColumnDocumentation(String tableName, String columnName)

{using(SqlCommand command =newSqlCommand(@"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);returncommand.ExecuteScalar()asString;

}

}

我们的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.Test\Feng.Test\Model1.edmx"

得到效果图如下:

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
 
© 2005- 王朝網路 版權所有 導航