如何修改Entity Framework Db Frist模式下的Entity继承关系?
1、准备工作
Db Frist创建实体数据模型(创建edmx并不是重点,各位随意即可),此处取名ZeroCodeDB,所得文件如图所示;其中红框中的文件(ZeroCodeDB.tt)是各实体的生成的关键代码,即Entity的T4模板文件,本文正是要对此文件动刀。
Demo父类代码准备如下,后续文章将会演示如何使实体User继承DemoClass、IDemoInterface<out TKey>。
using System; namespace ZeroCode.DemoLib { public class DemoClass{ } public interface IDemoInterface<out TKey> where TKey : IEquatable<TKey> { TKey Id { get; } } }
2、分析Entity类名是如何生成的
打开ZeroCodeDB.tt文件,找到Entity的类名生成方法EntityClassOpening()如下方左图所示,对应生成的User实体类名如右图红框所示,即EntityClassOpening()方法生成了字符串 “public partial class User ”,那么只要对该方法进行操作就可以实现我们的目的了。
接下来将从情节假设中演示如何修改Entity的继承关系。
(注:T4模板代码高亮需要安装T4模板编辑器,工具-->扩展和更新-->联机-->搜索“T4 editor”)
情景一:继承某类
情景假设:不需要EF生成的继承关系,将所有实体都继承 ZeroCode.DemoLib.DemoClass
完成上述情景需要两个步骤:
- 在ZeroCodeDB.tt代码中添加类库ZeroCode.DemoLib的引用;
- 替换 _code.StringBefore(" : ", _typeMapper.GetTypeName(entity.BaseType)),保存运行T4模板。
情景二:实现某泛型接口
情景假设:需要EF生成继承关系的同时并实现IDemoInterface<out TKey>泛型接口,实体主键的类型作为泛型
完成上述情景需要四个步骤:
- 在ZeroCodeDB.tt代码中添加类库ZeroCode.DemoLib的引用;
- 在TypeMapper类添加一个获取实体主键类型的方法(见下方图2);
- 在CodeStringGenerator类添加一个返回实体继承关系的方法(见下方图3);
- 替换 _code.StringBefore(" : ", _typeMapper.GetTypeName(entity.BaseType)),保存运行T4模板。
public string GetEntityInheritString(EntityType entity) { string baseTypeName= _typeMapper.GetTypeName(entity.BaseType); string idType=_typeMapper.GetIdKeyType(entity); string customBase=string.Format( CultureInfo.InvariantCulture, "{0}IDemoInterface<{1}>", string.IsNullOrEmpty(baseTypeName)?"":",", idType); return _code.StringBefore(" : ", baseTypeName + customBase); } public string GetIdKeyType(EntityType type) { if(type.KeyMembers.Count>0) { EdmMember meb=((EdmMember)type.KeyMembers.FirstOrDefault()); return meb==null?null: GetTypeName(meb.TypeUsage); } return null; }