Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >EntityFramework Core 自动绑定模型映射

EntityFramework Core 自动绑定模型映射

作者头像
潘成涛
发布于 2018-07-09 08:48:20
发布于 2018-07-09 08:48:20
1.3K00
代码可运行
举报
文章被收录于专栏:程序员与猫程序员与猫
运行总次数:0
代码可运行

笔者最近在和同事共同开发项目时,需要从他们提供的包含数据库实体类型的类库中读取实体信息绑定到自己的项目中(但是都在同一个解决方案里),所以很直接的一种方式就是把项目中所有的实体都以 public DbSet<Blog> Blogs { get; set; } 的形式加入到自己的 Context 中,但是这显然十分麻烦,而且如果又新增或减少了实体,每次又得在Context中做修改。

先放上示例的两个实体,假设它们都处于Synyi.EntityDemo这个项目类库中。其实IEntity是一个空接口,起指示作用。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
namespace Synyi.EntityDemo
{
    public class Blog : IEntity
    {
        public int BlogId { get; set; }
        public string Url { get; set; }
    
        public List<Post> Posts { get; set; }
    }
    
    public class Post : IEntity
    {
        public int PostId { get; set; }
        public string Title { get; set; }
        public string Content { get; set; }
    
        public int BlogId { get; set; }
        public Blog Blog { get; set; }
    }
}

所以有没有什么办法可以直接让 EntityFramework Core 来代劳这项工作呢?从这个想法出发,其实我们很自然地就可以想到 Context 中的 OnModelCreating 方法,在传统的 EF 6中,它也是作为实体模型属性映射的方法容器存在。如果大家看过笔者之前的那篇《EntityFramework Core 学习扫盲》,就会知道 Fluent Api 的使用都是在这个方法中的。它的方法签名如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
protected internal virtual void OnModelCreating(ModelBuilder modelBuilder)
{
}

配置的方法容器找到了,读取实体信息也是水到渠成的一件事,我们可以直接利用对程序集的反射读取所有的内部实体信息。代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var entityTypes = Assembly.Load(new AssemblyName("存放实体类型的程序集名称")).GetTypes()
    .Where(type => !string.IsNullOrWhiteSpace(type.Namespace))
    .Where(type => type.GetTypeInfo().IsClass)
    .Where(type => type.GetTypeInfo().BaseType != null)
    .Where(type => typeof(IEntity).IsAssignableFrom(type)).ToList();

其中 typeof(IEntity).IsAssignableFrom(type) 只是为了能获取到确定的继承了 IEntity 接口的实体而已。在这一步以后,通过查看 modelBuilder 上的相应方法,我们找到了 FindEntityTypeAddEntityType 方法。所以最后的代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.UseSqlServer(
        "Server=(localdb)\\MSSQLLocalDB;Database=ExampleDb;Trusted_Connection=True;MultipleActiveResultSets=true");
}

protected override void OnModelCreating(ModelBuilder builder)
{
    var entityTypes = Assembly.Load(new AssemblyName("存放实体类型的程序集名称")).GetTypes()
        .Where(type => !string.IsNullOrWhiteSpace(type.Namespace))
        .Where(type => type.GetTypeInfo().IsClass)
        .Where(type => type.GetTypeInfo().BaseType != null)
        .Where(type => typeof(IEntity).IsAssignableFrom(type)).ToList();

    foreach (var entityType in entityTypes)
    {
        //  防止重复附加模型,否则会在生成指令中报错
        if (builder.Model.FindEntityType(entityType) != null)
            continue;

        builder.Model.AddEntityType(entityType);
    }

    base.OnModelCreating(builder);
}

使用 Add-Migration XXUpdate-Database 指令后,我们的 ExampleDb 中就生成了相应的数据库表,一些隐藏的诸如“实体中命名为 Id 或者 ClassName+Id 的属性将自动设置为主键”的规则也会自动生效。假如目标数据库是类似于 PostgreSql 这种,数据库的表名和列名都得定义成小写字母,否则在 sql 时将不得不使用双引定义,十分的麻烦。所幸我们也可以直接在 OnModelCreating 方法中指定这一项规则。在上述方法末尾加上如下代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
foreach (var entity in builder.Model.GetEntityTypes())
{
    var currentTableName = builder.Entity(entity.Name).Metadata.Relational().TableName;
    builder.Entity(entity.Name).ToTable(currentTableName.ToLower());

    var properties = entity.GetProperties();
    foreach (var property in properties)
        builder.Entity(entity.Name).Property(property.Name).HasColumnName(property.Name.ToLower());
}

至于其他的配置,就要靠大家去挖掘了。

消失的 EntityTypeConfiguration

在传统的 EF 编程中,大家对 EntityTypeConfiguration 应该都十分的熟悉。比如如下的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class BlogConfiguration : EntityTypeConfiguration<Blog>
{
    public BlogConfiguration()
    {
        ToTable("Blogs");
        HasKey(x => x.Id);
        Property(x => x.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity).HasColumnName("BlogId");
        Property(x => x.Title).HasMaxLength(175);
        HasRequired(x => x.Url).WithRequiredPrincipal();
    }
}

// 在 OnModelCreating 方法中加入以下代码
modelBuilder.Configurations.Add(new BlogConfiguration());

就是这样一个好用的东西,却没有随着 EF 的迁移而保留下来,在 EF Core 中,我们已经看不到它的身影了,残念ですね。不过这也不是多难解决的事情,Github上已经有人给出了相关的解决方案

做些简单的分析——一句比较完整的Fluent Api 设置方式形如 builder.Entity<Blog>().ToTable("Blogs"); 所以我们只要抓住 builder.Entity<XXX>()的返回类型 EntityTypeBuilder 做文章即可。笔者在下面也给出另一种接口+反射方式的实现(第二个参考链接中的代码并不能直接使用)。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public interface IEntityTypeConfiguration
{
}

public class BlogConfiguration : IEntityTypeConfiguration
{
    public BlogConfiguration(ModelBuilder builder)
    {
        builder.Entity<Blog>().ToTable("Blogs");
    }
}

public static class ModelBuilderExtensions
{
    public static void ExecuteConfigurations(this ModelBuilder modelBuilder,string assemblyName)
    {
        var configurationTypes = Assembly.Load(new AssemblyName(assemblyName)).GetTypes()
            .Where(type => !string.IsNullOrWhiteSpace(type.Namespace))
            .Where(type => type.GetTypeInfo().IsClass)
            .Where(type => type.GetTypeInfo().BaseType != null)
            .Where(type => typeof(IEntityTypeConfiguration).IsAssignableFrom(type))
            .ToList();

        foreach (var type in configurationTypes)
            Activator.CreateInstance(type, modelBuilder);
    }
}

// 在 OnModelCreating 方法中加入以下代码
builder.ExecuteConfigurations("存放实体配置的程序集名称");
base.OnModelCreating(builder);

至此,Entity Framework Core 中的自动绑定实体映射应该就告一段落了,其他的功能也很容易基于上文扩展。如果大家有更好的想法,也可以在评论中留言(这语气听起来就好像自己的文章真的会有很多读者一样)。

参考资料

  1. 《Model configuration: Entity type configuration can be factored into a class》
  2. 《Organizing Fluent Configurations into Separate Classes in EF Core 1.0》
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-07-08 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Entity Framework Core 实现全局查询过滤
微软在 Entity Framework Core 2+ 中引入了全局查询过滤器,简化了构建多租户应用程序和实体软删除的复杂度。这篇文章我将通过代码的形式对全局过滤查询进行详细的讲解。在讲解前我们先来简单说一下什么是多租户,所谓多租户简单来说是指一个单独的实例可以为多个组织服务。多租户技术为共用的数据中心内如何以单一系统架构与服务提供多数客户端相同甚至可定制化的服务,并且仍然可以保障客户的数据隔离。 接下来我们先来看一个例子,我们假定多个租户使用同一个数据库,同一个Schema,区分租户是根据表中的 tId 区分。我们新建一个项目,在项目中重写 DbContext 上下文里的 OnModelCreating 方法,在这个方法中我们使用 HasQueryFilter 方法进行软删除。
喵叔
2020/09/08
1.2K0
Entity Framework 一对多关系映射
EF中关系映射也是一个很关键的内容,关系映射和属性映射一样,也是在 OnModelCreating 中配置映射。EF中的关系映射有如下三种:
喵叔
2020/09/08
1.1K0
Entity Framework 一对多关系映射
.NET Core开发实战(第29课:定义仓储:使用EF Core实现仓储层)--学习笔记
映射关系,针对每一个领域模型创建一个 EntityTypeConfiguration
郑子铭
2021/01/13
2.6K0
.NET Core开发实战(第29课:定义仓储:使用EF Core实现仓储层)--学习笔记
.NET EF Core(Entity Framework Core)
1、Entity Framework Core(EF Core)是微软官方的ORM框架。优点:功能强大、官方支持、生产效率高、力求屏蔽底层数据库差异;缺点:复杂、上手门槛高、不熟悉EFCore的话可能会进坑。 2、Dapper。优点:简单,N分钟即可上手,行为可预期性强;缺点:生产效率低,需要处理底层数据库差异。 3、EF Core是 模型驱动 (Model-Driven)的开发思想,Dapper是 数据库驱动(DataBase-Driven)的开发思想的。没有优劣,只有比较。 4、性能: Dapper等≠性能高;EF Core≠性能差。 5、EF Core是官方推荐、推进的框架,尽量屏蔽底层数据库差异,.NET开发者必须熟悉,根据的项目情况再决定用哪个。
鱼找水需要时间
2024/03/23
1.1K0
.NET EF Core(Entity Framework Core)
登录注册的小项目对比.Net Core与 .Net Framework的一些区别
UserSys.IServices:主要有实体和对实体的配置,还有对实体的操作接口
张哥编程
2024/12/19
1250
登录注册的小项目对比.Net Core与 .Net Framework的一些区别
【愚公系列】2023年02月 .NET/C#知识点-使用控制台手搭webapi框架
WebAPI是一种协议,用于允许网络应用程序(如浏览器)与网络服务器(如Web服务器)之间进行通信。它可以用于处理数据,访问数据库,处理图像和视频,以及进行其他高级功能。
愚公搬代码
2023/03/16
1.6K0
【愚公系列】2023年02月 .NET/C#知识点-使用控制台手搭webapi框架
小技巧 EntityFrameworkCore 实现 CodeFirst 通过模型生成数据库表时自动携带模型及字段注释信息
今天分享自己在项目中用到的一个小技巧,就是使用 EntityFrameworkCore 时我们在通过代码去 Update-Database 生成数据库时如何自动将代码模型上的注释和字段上的注释携带到数据库中,方便后续在数据库直接查看各个表和各个字段的含义。
乌拉栋
2022/12/16
8690
小技巧 EntityFrameworkCore 实现 CodeFirst 通过模型生成数据库表时自动携带模型及字段注释信息
ef和mysql使用(二)--让mysql支持EntityFramework.Extended实现批量更新和删除
我们都知道Entity Framework 中不能同时更新多条记录,但是一个老外写的扩展库可以实现此功能EntityFramework.Extended,但是如何是mysql数据库要怎么实现呢
yaphetsfang
2020/07/30
1.4K0
使用Entity Framework Core访问数据库(Oracle篇)
本篇主要讲一下关于Entity Framework Core访问oracle数据库的采坑。。
GuZhenYin
2019/05/25
2.9K0
C#之反射、元数据详解
  在本节中主要讲述自定义特性、反射。自定义特性允许把自定义元数据与程序元素关联起来。这些元数据是在编译过程中创建的,并嵌入程序集中。反射是一个普通的术语,它描述了在运行过程中检查和处理程序元素的功能。例如,反射运行完成以下任务:
小世界的野孩子
2019/09/11
1.6K0
EntityFramework Core 学习扫盲
0. 写在前面 本篇文章虽说是入门学习,但是也不会循规蹈矩地把EF1.0版本一直到现在即将到来的EF Core 2.0版本相关的所有历史和细节完完整整还原出来。在后文中,笔者会直接进入正题,所以这篇文章仍然还是需要一定的EF ORM基础。 对于纯新手用户,不妨先去看看文末链接中一些优秀博客,笔者当初也是从这些博客起家,也从中得到了巨大的帮助。当然了,官方教程同样至关重要,笔者之前也贡献过部分EF CORE 官方文档资料(基本都是勘误,逃…),本篇文章中很多内容都是撷取自官方的英文文档和示例。 下文示例中
潘成涛
2018/01/18
9.9K0
使用identity+jwt保护你的webapi(一)——identity基础配置
用户模块几乎是每个系统必备的基础功能,如果每次开发一个新项目时都要做个用户模块,确实非常无聊。好在asp.net core给我们提供了Identity,使用起来也是比较方便,如果对用户这块需求不是非常个性化的话,identity是一个不错的选择。
xhznl
2021/10/18
2.1K0
使用identity+jwt保护你的webapi(一)——identity基础配置
C# 数据操作系列 - 6 EF Core 配置映射关系
在《C# 数据操作系列 - 5. EF Core 入门》篇中,我们简单的通过两个类演示了一下EF增删改查等功能。细心的小伙伴可能看了生成的DDL SQL 语句,在里面发现了些端倪。没看的小伙伴也不急,这就贴出来。
程序员小高
2020/05/16
3K0
EF Core关系配置
关系配置: EF Core中实体之间关系的配置的套路: HasXXX(…).WithXXX(…); 有XXX、反之带有XXX。 XXX可选值One、Many。
鱼找水需要时间
2024/03/24
4450
EF Core关系配置
造轮子之多语言管理
多语言也是我们经常能用到的东西,asp.net core中默认支持了多语言,可以使用.resx资源文件来管理多语言配置。 但是在修改资源文件后,我们的应用服务无法及时更新,属实麻烦一些。我们可以通过扩展IStringLocalizer,实现我们想要的多语言配置方式,比如Json配置,PO 文件配置,EF数据库配置等等。 这里我们选用数据库配置的方式,直接查询数据库的多语言配置进行转换。
饭勺oO
2023/10/18
3260
造轮子之多语言管理
efcore分表分库原理解析
ShardingCore 易用、简单、高性能、普适性,是一款扩展针对efcore生态下的分表分库的扩展解决方案,支持efcore2+的所有版本,支持efcore2+的所有数据库、支持自定义路由、动态路由、高性能分页、读写分离的一款组件,如果你喜欢这组件或者这个组件对你有帮助请点击下发star让更多的.neter可以看到使用
呆呆
2021/10/09
1.3K0
从头编写 asp.net core 2.0 web api 基础框架 (4) EF配置
Github源码地址:https://github.com/solenovex/Building-asp.net-core-2-web-api-starter-template-from-scratch 前三部分弄完,我们已经可以对内存数据进行CRUD的基本操作,并且可以在asp.net core 2中集成Nlog了。 下面继续: Entity Framework Core 2.0 Entity Framework 是ORM(Object-Relational-Mapping)。ORM是一种让你可以使用面向
solenovex
2018/03/01
2.4K0
从头编写 asp.net core 2.0 web api 基础框架 (4) EF配置
.NET 云原生架构师训练营(模块二 基础巩固 EF Core 关系)--学习笔记
2.4.4 EF Core -- 关系 一对多 一对一 多对多 示例 关系:https://docs.microsoft.com/zh-cn/ef/core/modeling/relationship
郑子铭
2020/12/29
6340
.NET 云原生架构师训练营(模块二 基础巩固 EF Core 关系)--学习笔记
C# 根据前台传入实体名称,动态查询数据
项目中时不时遇到查字典表等数据,只需要返回数据,不需要写其他业务,每个字典表可能都需要写一个接口给前端调用,比较麻烦,所以采用下面这种方式,前端只需传入实体名称即可,例如:SysUser
郑子铭
2023/08/29
4280
C# 根据前台传入实体名称,动态查询数据
01-EF Core笔记之创建模型
使用EF Core的第一步是创建数据模型,模型建的好,下班走的早。EF Core本身已经设置了一系列约定来帮我们快速的创建模型,例如表名、主键字段等,毕竟约定大于配置嘛。如果你想改变默认值,很简单,EF Core提供了Fluent API或Data Annotations两种方式允许我们定制数据模型。
拓荒者IT
2019/09/23
3.4K0
推荐阅读
相关推荐
Entity Framework Core 实现全局查询过滤
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验