EntityFramework 实体拆分和表拆分

简介: 原文:EntityFramework 实体拆分和表拆分之前有人问过 EF 如何进行实体拆分和表拆分?我记得当时认为不可能,理由忘记了,后来又有人发了一段配置截图,发现原来是可以的,不记录的东西容易忘掉,关于 EF 实体拆分和表拆分,下面是自己的一些整理。
原文: EntityFramework 实体拆分和表拆分

之前有人问过 EF 如何进行实体拆分和表拆分?我记得当时认为不可能,理由忘记了,后来又有人发了一段配置截图,发现原来是可以的,不记录的东西容易忘掉,关于 EF 实体拆分和表拆分,下面是自己的一些整理。

两个概念:

  • 实体拆分:一个实体拆分成多个表,如 Blog 实体,可以拆分成 Blogs 和 BlogDetails 两个表。
  • 表拆分:一个表拆分成多个实体,如 Posts 表,可以拆分成 Post 和 PostDetail 两个实体。

1. 实体拆分

配置代码:

public class BloggingContext : DbContext
{
    public BloggingContext()
        : base("name=ef_split_dbcontext")
    {
    }

    public DbSet<Blog> Blogs { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>()
            .Map(m =>
            {
                m.Properties(t => new { t.Id, t.Title, t.Url });
                m.ToTable("Blogs");
            })
            .Map(m =>
            {
                m.Properties(t => new { t.Id, t.Remark });
                m.ToTable("BlogDetails");
            });

        base.OnModelCreating(modelBuilder);
    }
}

public class Blog
{
    [Key]
    public int Id { get; set; }
    public string Title { get; set; }
    public string Url { get; set; }
    public string Remark { get; set; }
}

映射效果:

img_21943152b44d4f6eb4bc1bea6ea74ad5.png

测试代码:

using (var context=new BloggingContext())
{
    context.Blogs.Add(new Blog { Remark = "", Title = "EntityFramework 实体拆分和表拆分", Url = "http://www.cnblogs.com/xishuai/p/ef-entity-table-splitting.html" });
    context.SaveChanges();
}

测试结果为 Blogs 和 BlogDetails 表中,分别产生一条数据,即使 Remark 的值为空。

2. 表拆分

配置代码:

public class BloggingContext : DbContext
{
    public BloggingContext()
        : base("name=ef_split_dbcontext")
    {
    }

    public DbSet<Post> Posts { get; set; }
    public DbSet<PostDetail> PostDetails { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Post>()
            .HasKey(t => t.PostId);

        modelBuilder.Entity<PostDetail>()
            .HasKey(t => t.PostId);

        modelBuilder.Entity<PostDetail>()
            .HasRequired(t => t.Post)
            .WithRequiredPrincipal(t => t.PostDetail);

        modelBuilder.Entity<Post>().ToTable("Posts");
        modelBuilder.Entity<PostDetail>().ToTable("Posts");

        base.OnModelCreating(modelBuilder);
    }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public virtual PostDetail PostDetail { get; set; }
}

public class PostDetail
{
    public int PostId { get; set; }
    public string Remark { get; set; }

    public virtual Post Post { get; set; }
}

映射效果:

img_41042224cfdd74328082652e5e55de20.png

测试代码:

using (var context=new BloggingContext())
{
    context.Posts.Add(new Post { Title="EntityFramework 实体拆分和表拆分"});
    context.PostDetails.Add(new PostDetail {  Remark=""});
    context.SaveChanges();
}

测试结果为 Posts 表中产生一条数据,注意映射配置中的这段代码:modelBuilder.Entity<PostDetail>().HasRequired(t => t.Post).WithRequiredPrincipal(t => t.PostDetail);,我们一般在外键配置的时候会用到 HasRequired,Required 表示的意思是必须,还有一种写法是:modelBuilder.Entity<PostDetail>().HasOptional(t => t.Post).WithOptionalPrincipal(t => t.PostDetail);,关键词 Optional,但映射会抱下面错误:The entity types 'Post' and 'PostDetail' cannot share table 'Posts' because they are not in the same type hierarchy or do not have a valid one to one foreign key relationship with matching primary keys between them.

其实我的想法是,在上面测试代码中,用了两个 Add(而不是一个 Add,然后用 PostDetail 属性赋值),那会不会在 Posts 表中产生两条数据,但显然没有,因为我们在映射配置的时候,使用的是 Required,可以理解为“强制合并为一个表”,不论你怎么添加数据,都会只添加一条数据,另外,需要注意的是,在上面表拆分示例中,主实体是 Post,所以,如果只有 context.PostDetails.Add(new PostDetail { Remark=""});,会抱下面错误:Invalid data encountered. A required relationship is missing. Examine StateEntries to determine the source of the constraint violation.

参考:使用 Fluent API 配置/映射属性和类型

目录
相关文章
|
Java API Nacos
找不到`com.alibaba.nacos.api.utils.NetUtils`类
找不到`com.alibaba.nacos.api.utils.NetUtils`类
790 0
|
11月前
|
弹性计算 运维 Cloud Native
云原生架构的崛起与未来展望
在数字化转型的浪潮中,云原生架构凭借其高效、灵活和可扩展的特性,正逐渐成为企业IT战略的核心。本文旨在探讨云原生架构的定义、关键特性、实施优势以及面临的挑战,同时展望未来的发展趋势。通过深入分析,我们期望为读者提供一个关于云原生架构全面而深入的视角,助力企业在云计算时代做出更明智的决策。
291 30
|
存储 测试技术 Go
Golang框架实战-KisFlow流式计算框架(2)-项目构建/基础模块-(上)
KisFlow项目源码位于&lt;https://github.com/aceld/kis-flow,初始阶段涉及项目构建和基础模块定义。首先在GitHub创建仓库,克隆到本地。项目目录包括`common/`, `example/`, `function/`, `conn/`, `config/`, `flow/`, 和 `kis/`。`go.mod`用于包管理,`KisLogger`接口定义了日志功能,提供不同级别的日志方法。默认日志对象`kisDefaultLogger`打印到标准输出。
825 77
Golang框架实战-KisFlow流式计算框架(2)-项目构建/基础模块-(上)
|
存储 Linux 图形学
深度探索Linux操作系统 —— Linux图形原理探讨1
深度探索Linux操作系统 —— Linux图形原理探讨
385 7
|
负载均衡 监控 安全
Istio:微服务治理的超级英雄,一键解锁你的服务网格超能力,让管理复杂变简单!
【8月更文挑战第31天】随着云原生技术的发展,微服务架构成为主流,但其复杂性与管理难题也随之增加。Istio作为开源服务网格平台,通过独特的数据平面和控制平面设计,实现了微服务通信的透明管理,简化了治理复杂度。本文将对比Istio与传统微服务管理方法,详细介绍Istio的架构及其工作原理,包括Envoy代理、服务发现、负载均衡、流量管理、安全认证以及监控等功能。Istio不仅简化了微服务治理,还提供了强大的流量控制和安全机制,使开发者能更高效地管理应用。
469 2
|
传感器 搜索推荐 人机交互
虚拟现实中的人机交互设计:探索未来交互的无限可能
【8月更文挑战第26天】虚拟现实中的人机交互设计是一项充满挑战与机遇的技术领域。随着技术的不断进步和应用场景的不断拓展,我们有理由相信未来VR人机交互将更加自然、直观和个性化。设计师需要不断探索和创新以应对各种技术挑战和用户需求变化,为用户带来更加丰富和愉悦的交互体验。
|
数据挖掘 UED
ERP系统的用户体验与界面设计:提升用户满意度与操作效率
【7月更文挑战第29天】 ERP系统的用户体验与界面设计:提升用户满意度与操作效率
1281 1
【视频】R语言生存分析原理与晚期肺癌患者分析案例|数据分享(上)
【视频】R语言生存分析原理与晚期肺癌患者分析案例|数据分享
|
缓存 数据可视化 安全
开发阿里云 RPA 机器人的技巧
在当今数字化时代,机器人流程自动化(RPA)技术正逐渐成为企业提高效率和优化业务流程的重要手段。阿里云 RPA 作为一种强大的工具,为开发高效的机器人提供了丰富的功能和支持。本文将分享一些开发阿里云 RPA 机器人的技巧,帮助您更好地利用该平台的能力。
|
人工智能 安全 API
Unity优化——加速物理引擎1
Unity优化——加速物理引擎1
315 0