EF6.0 生成的代码中没有注释的解决方法
来源:互联网 发布:单身狗公仔淘宝 编辑:程序博客网 时间:2024/06/08 04:35
目录
- 目录
- 初试Entity Framework60
- 发现问题
- 先来回顾一下ef40生成的内容
- ef40 关系元数据不知道大家看不看反正我没仔细看过
- ef40 Container 声明以
- ef40 实体集合
- ef40 AddTo方法
- ef40 实体声明
- ef40 实体构造函数
- ef40 基元属性
- 再来看EF60生成的内容
- ef60 构造函数
- ef60 实体集声明
- ef60 实体声明
- 先来回顾一下ef40生成的内容
- 问题解决的必要性
- 解决问题
- 第一步 为edmx添加代码生成项也就是EF6x DBContext生成器
- 第二步 修改T4模板内容
- ModelContexttt文件
- Modeltt文件
- 总结
- 发现问题
初试Entity Framework6.0
之前一直在使用vs2010或者是vs2008,也一直使用的EF4.0一下的版本……在之前,也习惯了Model First的EF设计方式,因为感觉,在设计界面中可以更好的帮助构思;同时,在设计界面中也很容易的增加一些文字说明(这些说明会存在与最终生成的实体类中)。
发现问题
在安装的vs2013之后,我赶紧试了EF6.0……此处省略好几万字。
打开了一个以前设计并完成的项目,当中包含了edmx文件,我想看看ef6.0生成的代码到底和ef4.0有什么不同。
结果发现:ef6.0(T4模板)生成的cs文件中,竟然没有包含注释(edmx中的文档),这个让我情何以堪啊。
先来回顾一下ef4.0生成的内容
ef4.0 关系元数据(不知道大家看不看,反正我没仔细看过)
#region EDM 关系源元数据[assembly: EdmRelationshipAttribute("Models", "HospitalProject", "Hospital", System.Data.Metadata.Edm.RelationshipMultiplicity.One, typeof(HNWMS.EFData.Hospital), "Project", System.Data.Metadata.Edm.RelationshipMultiplicity.One, typeof(HNWMS.EFData.Project))]///... ...[assembly: EdmRelationshipAttribute("Models", "UserMyDisk", "User", System.Data.Metadata.Edm.RelationshipMultiplicity.One, typeof(HNWMS.EFData.User), "MyDisk", System.Data.Metadata.Edm.RelationshipMultiplicity.Many, typeof(HNWMS.EFData.MyDisk))]#endregion
ef4.0 Container 声明以
ef4.0中Container继承自ObjectContext
构造函数(默认生成的)有三个。
/// <summary> /// 没有元数据文档可用。 /// </summary> public partial class Container : ObjectContext
ef4.0 实体集合
有公共的带有get访问器的属性,也有对应的私有字段。完全面向对象的写法;唯一不好的就是,没有自动生成实体集合的注释内容(summary)。
/// <summary> /// 没有元数据文档可用。 /// </summary> public ObjectSet<User> Users { get { if ((_Users == null)) { _Users = base.CreateObjectSet<User>("Users"); } return _Users; } } private ObjectSet<User> _Users;
ef4.0 AddTo方法
虽然表明了“已弃用”,但是,在其他地方调用的时候还是很方便,起码很直接。
/// <summary> /// 用于向 Users EntitySet 添加新对象的方法,已弃用。请考虑改用关联的 ObjectSet<T> 属性的 .Add 方法。 /// </summary> public void AddToUsers(User user) { base.AddObject("Users", user); }
ef4.0 实体声明
加入了很多Attribute的声明,说实在的,我从来没有注意过这些东西,也不知道做什么用的。
/// <summary> /// 用户基类(同时描述总部人员) /// </summary> [EdmEntityTypeAttribute(NamespaceName="Models", Name="User")] [Serializable()] [DataContractAttribute(IsReference=true)] [KnownTypeAttribute(typeof(ProjectManager))] [KnownTypeAttribute(typeof(HospitalServicer))] [KnownTypeAttribute(typeof(NursingWorker))] public partial class User : EntityObject
ef4.0 实体构造函数
庞大到不敢看,参数是所有属性的排列,然后加上了个global::用以排除类型冲突;在开发的过程中,我似乎没有使用过实体构造函数来构造实体的实例。
public static User CreateUser(global::System.String code, global::System.String loginPassword, global::System.String realName, global::System.String mobilePhoneNO, global::System.String xType, global::System.String iDCordNO)
ef4.0 基元属性
同实体集合一般,完全符合面向对象的写法,有属性,就有对应的字段存在。另外再set访问器中还显示的触发了“自跟踪实体”的四个事件(具体什么是自跟踪实体,这里不做复述。)
/// <summary> /// 用户编码 /// </summary> /// <LongDescription> /// 编码规则:
U开头+4位数字顺序码
若4位顺序码达到9999则为
UA开头+3为数字顺序码
以此类推
 /// </LongDescription> [EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)] [DataMemberAttribute()] public global::System.String Code { get { return _Code; } set { if (_Code != value) { OnCodeChanging(value); ReportPropertyChanging("Code"); _Code = StructuralObject.SetValidValue(value, false); ReportPropertyChanged("Code"); OnCodeChanged(); } } } private global::System.String _Code;
虽然,我在上边的描述中说了提到了很多关于ef4.0中的“不好”,但是这并不表示我不认同ef4.0。下面说几点我理解的ef的好处:
- 我还是很喜欢ef的,因为其简单、易用,配合上mvc、WCF Data Service很容易就完成一个解决方案;
- 我更加喜欢vs提供的edmx设计器,在这里我可以不借助其他“构思辅助”软件,就可以完成“数据设计”以及“数据关系”的梳理工作。
- 通过edmx我可以很容易的为“实体”“属性”“导航属性”添加“文档”(在最终的代码中为summary,这也是我写这篇文章的目的。)
因为解决方案中存在有一个edmx文件,在其他人接手改解决方案时,很容易就可以看到数据设计,很容易就可以理解数据关系。
所以,在大家都在“喊叫”EF code first的时候,我仍然使用着model or db first。所谓“仁者见仁智者见智,萝卜白菜各有所爱”,大牛们别喷我。谢谢^_&.
再来看EF6.0生成的内容
ef6.0 构造函数
不同于EF4.0,在生成的Container上方,并没有出现很多的“元数据”内容。打开这个类的时候,给我的第一感觉就是,啊!好简单啊。
Container继承自DBContext,至于与ObjectContext有什么不同,请大家找度娘或者MSDN。
public partial class Container : DbContext
ef6.0 实体集声明
与ef4.0首先不同在,实体集不再是ObjectSet类型的了,而是DBSet类型的了;其次,它简化了get和set访问器(同时少了对应字段的声明,到时符合了隐式属性访问器的声明方法)
不好再那里呢???注释那里去了,ef4.0最起码还有个 “没有元数据文档可用。”的注释。
public virtual DbSet<User> Users { get; set; }
ef6.0 实体声明
与ef4.0不同在,实体的构造函数不再那么臃肿,无参数,在内部也仅仅是为导航属性赋予了初始值;同时,属性的get和set也简化了,乍一看,这样一个类好像是谁写出来的Demo呢。
不过,与实体集声明 一般,注释那里去了,ef4.0中,可是把edmx中的“文档以及长说明”都生成在了summary中的。
public partial class User { public User() { this.SignIns = new HashSet<SignIn>(); this.MyMenus = new HashSet<MyMenu>(); this.MyDisks = new HashSet<MyDisk>(); } public string Code { get; set; } public string LoginPassword { get; set; } public string RealName { get; set; } public string MobilePhoneNO { get; set; } public string xType { get; set; } public string IDCordNO { get; set; } public virtual ICollection<SignIn> SignIns { get; set; } public virtual ICollection<MyMenu> MyMenus { get; set; } public virtual ICollection<MyDisk> MyDisks { get; set; } }
上面非常简单的和肤浅的叙述了ef4.0和ef6.0之间的区别,并阐述了我个人的好恶。
问题解决的必要性
看到这里,很多大牛可能会说“老弟,out man,大家现在都在2015,你还2013呢??”“不就是一个注释么?有那个必要么?”
小弟我解释一下,呵呵,有几年了,没有工作在第一线,没有进行过code的工作,所以对于vs和其他编辑器等,都不甚熟悉了……注释可是很重要的,尤其是符合vs要求的/// summary 注释,因为vs有智能提示啊,我想大家都见过也用过,当.的时候,就会出现很多该类型下的属性啊,方法啊…….拜托都是英文,如何分辨?就算你E文好,请问,你一个人开发应用系统的?
呵呵,有点强词夺理了。
总之,我要大吼一声“我要注释!不管是我写的代码的注释,还是生成的代码的注释,我都要!还要看的懂得注释。”
悄悄的告诉一些比我还菜的小鸟们,其实vs中代码的(符合规范的)注释,相当有用的,比如开发完成后,你可以通过注释生成chm类型或者help view2.x类型的帮助文件的(这里不多说)。
解决问题
第一步 为edmx添加“代码生成项”也就是“EF6.x DBContext生成器”
步骤:
- 在vs中打开edmx
- 随便找个空白的地方右键,然后选择“添加代码生成项”
- 然后在随后出现的窗口中选择“EF6.x DBContext生成器”,确定
- 验证:在解决方案资源管理器中,edmx文件下方就会出现你刚刚添加的“代码生成内容”,一般叫做Model.Context.tt 和Model.tt(其实这两个东西,就是T4模板;打开它,然后按“ctrl+s”的时候,它就会自动执行,并按照edmx文件中的设计,生成相关的Container 、DBSet、entity)
第二步 修改T4模板内容
Model.Context.tt文件
找到内容:
public string DbSet(EntitySet entitySet,System.Collections.Generic.IEnumerable<System.Data.Entity.Core.Metadata.Edm.GlobalItem> itemCollection) { return string.Format( CultureInfo.InvariantCulture, "{0} virtual DbSet<{1}> {2} {{ get; set; }}", Accessibility.ForReadOnlyProperty(entitySet), _typeMapper.GetTypeName(entitySet.ElementType), _code.Escape(entitySet), summary); }
这个方法是干什么的呢?其实就是返回一段类似下发代码的文本
public virtual DbSet<User> Users { get; set; }
更改成为:
public string DbSet(EntitySet entitySet,System.Collections.Generic.IEnumerable<System.Data.Entity.Core.Metadata.Edm.GlobalItem> itemCollection) { string summary = entitySet.ElementType.Documentation == null ? "(error message:not have summary in edmx.)" : entitySet.ElementType.Documentation.Summary; return string.Format( CultureInfo.InvariantCulture, "/// <summary>\r\n\t/// {3}的集合\r\n\t/// </summary>\r\n\t{0} virtual DbSet<{1}> {2} {{ get; set; }}", Accessibility.ForReadOnlyProperty(entitySet), _typeMapper.GetTypeName(entitySet.ElementType), _code.Escape(entitySet), summary); }
呵呵,你可能觉得,我写的Format中,不该美观。。。。。。我的解释是,反正这个T4最终不会被编译到程序集中,无所谓啦。
这样,最终产生的内容就类似与:
/// <summary>/// 用户基类(同时描述总部人员)的集合/// </summary>public virtual DbSet<User> Users { get; set; }
Model.tt文件
找到内容:
foreach (var entity in typeMapper.GetItemsToGenerate<EntityType>(itemCollection)){ fileManager.StartNewFile(entity.Name + ".cs"); BeginNamespace(code);#>
这段代码,就是根据实体的类型名称,产生一个独立的cs文件,并产生Namespace声明,若为类型添加注释,不就是在Namespace下边么……
更改成为:
string summary=string.Empty;foreach (var entity in typeMapper.GetItemsToGenerate<EntityType>(itemCollection)){ fileManager.StartNewFile(entity.Name + ".cs"); BeginNamespace(code); summary = entity.Documentation == null ? entity.Name : entity.Documentation.Summary;#>/// <summary>/// <#=summary#>/// </summary>
还没有完成,继续,找到
public string Property(EdmProperty edmProperty) { return string.Format(CultureInfo.InvariantCulture, "{0} {1} {2} {{ {3}get; {4}set; }}", Accessibility.ForProperty(edmProperty), _typeMapper.GetTypeName(edmProperty.TypeUsage), _code.Escape(edmProperty), _code.SpaceAfter(Accessibility.ForGetter(edmProperty)), _code.SpaceAfter(Accessibility.ForSetter(edmProperty))); } public string NavigationProperty(NavigationProperty navProp) { var endType = _typeMapper.GetTypeName(navProp.ToEndMember.GetEntityType()); return string.Format( CultureInfo.InvariantCulture, "{0} {1} {2} {{ {3}get; {4}set; }}", AccessibilityAndVirtual(Accessibility.ForNavigationProperty(navProp)), navProp.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? ("ICollection<" + endType + ">") : endType, _code.Escape(navProp), _code.SpaceAfter(Accessibility.ForGetter(navProp)), _code.SpaceAfter(Accessibility.ForSetter(navProp))); }
更改为:
public string Property(EdmProperty edmProperty) { return string.Format(CultureInfo.InvariantCulture, "/// <summary>\r\n\t/// {5}\r\n\t/// </summary>\r\n\t{0} {1} {2} {{ {3}get; {4}set; }}", Accessibility.ForProperty(edmProperty), _typeMapper.GetTypeName(edmProperty.TypeUsage), _code.Escape(edmProperty), _code.SpaceAfter(Accessibility.ForGetter(edmProperty)), _code.SpaceAfter(Accessibility.ForSetter(edmProperty)), edmProperty.Documentation == null ? "" : edmProperty.Documentation.Summary ); } public string NavigationProperty(NavigationProperty navProp) { var endType = _typeMapper.GetTypeName(navProp.ToEndMember.GetEntityType()); return string.Format( CultureInfo.InvariantCulture, "/// <summary>\r\n\t/// {5}\r\n\t/// </summary>\r\n\t{0} {1} {2} {{ {3}get; {4}set; }}", AccessibilityAndVirtual(Accessibility.ForNavigationProperty(navProp)), navProp.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? ("ICollection<" + endType + ">") : endType, _code.Escape(navProp), _code.SpaceAfter(Accessibility.ForGetter(navProp)), _code.SpaceAfter(Accessibility.ForSetter(navProp)), navProp.Documentation == null ? "" : navProp.Documentation.Summary ); }
然后“保存”,产生的cs文件中就类似与下边了:
/// <summary> /// 用户基类(同时描述总部人员) /// </summary> public partial class User { ...... /// <summary> /// 用户编码 /// </summary> public string Code { get; set; } ...... }
OK!这样就搞定了edmx生成内容中无注释的问题了。
再次大吼“注释有用!”
总结
总之,我个人觉得,在使用一个(别人能够归纳与一个系列的)新东西的时候,一定要从设计者的角度去考虑,每一样东西都是有用的。
- EF6.0 生成的代码中没有注释的解决方法
- PowerDesigner中生成SQL SERVER2005字段注释的解决方法
- PowerDesigner中生成SQL SERVER2005字段注释的解决方法
- PowerDesigner中生成SQL SERVER2005字段注释的解决方法
- keil V4中,中文注释代码出现乱码的解决方法
- 论如何看懂没有注释的代码
- PowerDesigner生成mysql数据库表结构的sql建表语句时没有comment注释的解决方法和去掉comment注释的解决方法
- 给ef6的实体模型 edmx文件加字段注释
- 没有注释的代码也属于垃圾代码范畴?
- 代码中特殊的注释
- Xcode中代码的注释
- Qt没有代码提醒功能的解决方法
- Xcode下没有代码提示的解决方法
- python-简单的makefile生成程序-没有注释
- MVC中code first方式开发,数据库的生成与更新(Ef6)
- MVC中code first方式开发,数据库的生成与更新(Ef6)
- MVC中code first方式开发,数据库的生成与更新(Ef6)
- 没有注释的后果
- ios xmpp研究探索:获取好友列表
- Google Dexmaker 代码解析(四)-- MethodId<D, R>
- 浅谈我对机器学习的理解
- 详细的介绍!CSS3 Transitions, Transforms和Animation使用简介与应用展示
- 100-git源代码管理
- EF6.0 生成的代码中没有注释的解决方法
- Web技术基础
- Burger - UVa 557 概率dp
- 谈谈我眼中的CSDN吧
- MySQL创建用户与授权方法
- RFID第一次作业第三题
- 101-开发技巧和一些常见的问题(1)
- MFC添加右键菜单
- 黑马程序员——Java编程语言学习总结 – IO流