EF6&EFCore 注册/使用实体类的正确姿势
首先回顾下EF中常规使用流程
1.新建实体类以及实体配置(data annotation或fluent api)
[Table("Users")]
public class Users
{
[Key]
public Guid Id { get; set; }
[StringLength()]
public string Name { get; set; }
}
2.新建数据库上下文类MyDbContext
public class MyDbContext : DbContext
{
public MyDbContext() { } public DbSet<Users> Users { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("connectionString");
} protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
3.开始欢乐的操作Users
using (MyDbContext context = new MyDbContext())
{
context.Users.FirstOrDefaultAsync(r => r.Name == "老王");
}
一切看起来都是很美好的,但假如有一天你面对上千个实体的时候,你可能会开始想用代码生成器.EF6中你还可以用modelBuilder.RegisterEntityType(type);那么现在又有一个新的要求,需要能同时使用data annotation和fluent api进行实体配置.自动根据约定注册实体,自动注册fluent api配置类.EF中注册实体的本质就是注册DbSet,方法非常多.
ok,直接贴代码,EF6:
/// <summary>
/// 注册某个程序集中所有<typeparamref name="TEntityBase"/>的非抽象实体子类
/// </summary>
/// <typeparam name="TEntityBase">实体基类</typeparam>
/// <param name="modelBuilder"></param>
/// <param name="assembly">注册程序集</param>
public static void RegisterEntitiesFromAssembly<TEntityBase>(this DbModelBuilder modelBuilder, Assembly assembly)
where TEntityBase : class
{
modelBuilder.RegisterEntitiesFromAssembly(assembly, r => !r.IsAbstract && r.IsClass && r.IsChildTypeOf<TEntityBase>());
} /// <summary>
/// 注册某个程序集中所有<typeparamref name="TEntityBase"/>的非抽象实体子类
/// </summary>
/// <typeparam name="TEntityBase">实体基类</typeparam>
/// <param name="modelBuilder"></param>
/// <param name="assembly">注册程序集</param>
/// <param name="assembly">注册程序集</param>
public static void RegisterEntitiesFromAssembly(this DbModelBuilder modelBuilder, Assembly assembly, Func<Type, bool> entityTypePredicate)
{
if (assembly == null)
throw new ArgumentNullException(nameof(assembly)); //反射得到DbModelBuilder的Entity方法
var entityMethod = modelBuilder.GetType().GetMethod("Entity"); //反射得到ConfigurationRegistrar的Add<TEntityType>方法
var addMethod = typeof(ConfigurationRegistrar)
.GetMethods()
.Single(m =>
m.Name == "Add"
&& m.GetGenericArguments().Any(a => a.Name == "TEntityType"));
//扫描所有fluent api配置类,要求父类型必须是EntityTypeConfiguration<TEntityType>
var configTypes = assembly
.GetTypesSafely()
.Where(t =>
!t.IsAbstract && t.BaseType != null && t.IsClass
&& t.BaseType.IsGenericType
&& t.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>)
)
.ToList(); HashSet<Type> registedTypes = new HashSet<Type>(); //存在fluent api配置的类,必须在Entity方法之前调用
configTypes.ForEach(mappingType =>
{
var entityType = mappingType.BaseType.GetGenericArguments().Single();
if (!entityTypePredicate(entityType))
return;
var map = Activator.CreateInstance(mappingType);
//反射调用ConfigurationRegistrar的Add方法注册fluent api配置,该方法会同时注册实体
addMethod.MakeGenericMethod(entityType)
.Invoke(modelBuilder.Configurations, new object[] { map }); registedTypes.Add(entityType);
}); //反射调用Entity方法 注册实体
assembly
.GetTypesSafely()
.Where(entityTypePredicate)
.ForEach_(r =>
{
entityMethod.MakeGenericMethod(r).Invoke(modelBuilder, new object[]);
});
}
EFCore:
/// <summary>
/// 注册某个程序集中所有<typeparamref name="TEntityBase"/>的非抽象子类为实体
/// </summary>
/// <typeparam name="TEntityBase">实体基类</typeparam>
/// <param name="modelBuilder"></param>
/// <param name="assembly">注册程序集</param>
public static void RegisterEntitiesFromAssembly<TEntityBase>(this ModelBuilder modelBuilder, Assembly assembly)
where TEntityBase : class
{
modelBuilder.RegisterEntitiesFromAssembly(assembly, r => !r.IsAbstract && r.IsClass && r.IsChildTypeOf<TEntityBase>());
} /// <summary>
/// 注册某个程序集中所有<typeparamref name="TEntityBase"/>的非抽象子类为实体
/// </summary>
/// <typeparam name="TEntityBase">实体基类</typeparam>
/// <param name="modelBuilder"></param>
/// <param name="assembly">注册程序集</param>
/// <param name="assembly">注册程序集</param>
public static void RegisterEntitiesFromAssembly(this ModelBuilder modelBuilder, Assembly assembly, Func<Type, bool> entityTypePredicate)
{
if (assembly == null)
throw new ArgumentNullException(nameof(assembly)); //反射得到ModelBuilder的ApplyConfiguration<TEntity>(...)方法
var applyConfigurationMethod = modelBuilder.GetType().GetMethod("ApplyConfiguration"); //所有fluent api配置类
var configTypes = assembly
.GetTypesSafely()
.Where(t =>
!t.IsAbstract && t.BaseType != null && t.IsClass
&& t.IsChildTypeOfGenericType(typeof(IEntityTypeConfiguration<>))).ToList(); HashSet<Type> registedTypes = new HashSet<Type>();
//存在fluent api配置的类,必须在Entity方法之前调用
configTypes.ForEach(mappingType =>
{
var entityType = mappingType.GetTypeInfo().ImplementedInterfaces.First().GetGenericArguments().Single(); //如果不满足条件的实体,不注册
if (!entityTypePredicate(entityType))
return; var map = Activator.CreateInstance(mappingType);
applyConfigurationMethod.MakeGenericMethod(entityType)
.Invoke(modelBuilder, new object[] { map }); registedTypes.Add(entityType);
}); assembly
.GetTypesSafely()
.Where(r => !registedTypes.Contains(r))
.Where(entityTypePredicate)
.ForEach_(r =>
{
//直接调用Entity方法注册实体
modelBuilder.Entity(r);
});
}
如何使用(EFCore,EF6类似)
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.RegisterEntitiesFromAssembly<IEntity>(this.GetType().Assembly);
} using (MyDbContext context = new MyDbContext())
{
context.Set<Users>().FirstOrDefaultAsync(r => r.Name == "老王");
}
data annotation和fluent api同时使用怎么用?,其中data annotation与fluent api冲突时,以fluent api为准,如Users的表名称最终会映射为"Users___",见代码
[Table("Users")]
public class Users
{
[Key]
public Guid Id { get; set; }
[StringLength()]
public string Name { get; set; }
}
public class UsersMapping : IEntityTypeConfiguration<Users>
{
public void Configure(EntityTypeBuilder<Users> builder)
{
builder.ToTable("Users___");
}
}
不用你写 public DbSet<Users> Users{get;set;},也不用你写一大堆的,modelBuilder.ApplyConfiguration<Users>(new UserMpping());
一句代码modelBuilder.RegisterEntitiesFromAssembly<IEntity>(this.GetType().Assembly);搞定所有的实体与实体配置
代码:https://github.com/280780363/Lazy
EF6&EFCore 注册/使用实体类的正确姿势的更多相关文章
- Java 基础(三)| IO流之使用 File 类的正确姿势
为跳槽面试做准备,今天开始进入 Java 基础的复习.希望基础不好的同学看完这篇文章,能掌握泛型,而基础好的同学权当复习,希望看完这篇文章能够起一点你的青涩记忆. 一.什么是 File 类? java ...
- 无法为具有固定名称“MySql.Data.MySqlClient”的 ADO.NET 提供程序加载在应用程序配置文件中注册的实体框架提供程序类型“MySql.Data.MySqlClient.MySqlProviderServices,MySql.Data.Entity.EF6”
"System.InvalidOperationException"类型的未经处理的异常在 mscorlib.dll 中发生 其他信息: 无法为具有固定名称"MySql. ...
- 【技术】JavaSE环境下JPA实体类自动注册
在没有容器支持的环境下,JPA的实体类(Entity)一般要在persistence.xml中逐个注册,类似下面这样: <?xml version="1.0" encodin ...
- 讨论一下hibernate如何动态注册一个动态生成的实体类
如何动态生成实体类请参考这篇博文:http://www.cnblogs.com/anai/p/4269858.html 下面说说得到实体类后,如何能使用hibernate的接口来进行数据访问. 我们都 ...
- .NET Core、EF、Dapper、MySQL 多种方式实现数据库操作(动态注册实体类)
目录 前言 一.技术选型 二.遇到的坑 2.1..NET Core 下 EF 的问题 2.2.数据库实体类的注册 切记坑 前言 最近在学习.研究 .NET Core 方面的知识,动手搭建了一些小的 D ...
- 使用.net core efcore根据数据库结构自动生成实体类
源码 github,已更新最新代码 https://github.com/leoparddne/GenEntities/ 使用的DB是mysql,所有先nuget一下mysql.data 创建t4模板 ...
- NetCore +EFCore+SqlServer根据数据库生成实体类到项目中
转载自:https://www.cnblogs.com/yangjinwang/p/9516988.html 1.点击“工具”->“NuGet包管理器”->“程序包管理器控制台” 分别安装 ...
- 在efcore 中创建类 通过实现IEntityTypeConfiguration<T>接口 实现实体类的伙伴类 实现FluentApi
1 创建实体类: public partial class NewsCategory : IAggregationRoot { public NewsCategory() { } public Gui ...
- ASP.NET Core EFCore 之DBFirst 自动创建实体类和数据库上下文
通过引用Nuget包添加实体类 运行 Install-Package Microsoft.EntityFrameworkCore.SqlServer 运行 Install-Package Micros ...
随机推荐
- C# List排序,附加使用Linq排序
首先先介绍一下平时最常用的几种排序方法. 第一种:实体类实现IComparable接口,而且必须实现CompareTo方法 实体类定义如下: class Info:IComparable { publ ...
- Linux常用命令使用
系统基础相关 使用root用户的环境变量切换到root用户 su - 显示当前工作路径 pwd 显示当前系统默认语言及键盘布局 localectl 显示系统中能支持的所有语言 localectl li ...
- hdu 4970 树状数组 “改段求段”
题意:塔防.给1--n,给出m个塔,每个塔有攻击力,给出k个怪兽的位子和血量,问有几只可以到达n点. 今天刚刚复习了树状数组,就碰到这个题,区间更新.区间求和类型.第三类树状数组可以斩. 注意一下大数 ...
- node/webpack/react
node是运行引擎,通过他可以直接在后端运行js语法 webpack是打包工具 react是前端框架 通过 npm 使用 React 我们建议在 React 中使用 CommonJS 模块系统,比如 ...
- python tcp,udp简单使用
import socket host = '127.0.0.1' port = 9999 #创建一个tcp socket套接字 tcp_server = socket.socket(socket.AF ...
- C#反射获取属性值和设置属性值
/// /// 获取类中的属性值 /// public string GetModelValue(string FieldName, object obj) { try { Type Ts = obj ...
- .NET Core R2安装及示例教程
.NET Core R2安装及示例教程 Install for Windows - Visual Studio 2015 1 Download Visual Studio 2015 Make sure ...
- make -j 4 echo !$
make -j 4 #以cpu四核编译 !$上一次命令空格后的部分
- centos 安装 htop
centos-install-htop http://elearning.wsldp.com/pcmagazine/centos-install-htop/
- 【Excle数据透视】如何创建一个数据透视表
数据透视表可以汇总.分析.浏览和提供工作表数据或外部数据源的汇总数据 创建方法一 通过”插入”创建,具体操作请看下图: 创建方法二 通过快捷键创建 使用[ALT+D+P]创建 首先按下alt键,然后依 ...