EntityFramework 6.x和EntityFramework Core关系映射中导航属性必须是public?

前言

不知我们是否思考过一个问题,在关系映射中对于导航属性的访问修饰符是否一定必须为public呢?如果从未想过这个问题,那么我们接下来来探讨这个问题。

EF 6.x和EF Core 何种情况下必须配置映射关系?

在EF 6.x中我们创建如下示例类。

    public partial class Customer
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Email { get; set; }
        public ICollection<Order> Orders { get; set; } = new List<Order>();
    }
    public class Order : BaseEntity
    {
        public int Quantity { get; set; }
        public string Code { get; set; }
        public decimal Price { get; set; }
        public int CustomerId { get; set; }
        public Customer Customer { get; set; }
    }

上述我们不显式配置映射关系,EF和EF Core会根据约定来配置,同样达到如我们期望的,无论是EF 6.x还是EF Core中通过Inlcude进行显式加载有两种方式,一种是基于字符串,另外一种则是通过lamda表达式的方式(命名空间存在于System.Data.Entity),接下来我们来看下:

            using (var ctx = new EfDbContext())
            {
                ctx.Database.Log = Console.WriteLine;

                var customers = ctx.Customers.Include(d => d.Orders).ToList();
            };

这样是我们一直以来最正常的操作,如前言所叙,那么导航属性难道必须是public吗?接下来我们来试试。我们尝试将Orders导航属性配置成如下私有的。

 private ICollection<Order> Orders { get; set; } = new List<Order>();

因为其为私有,若通过lambda表达式肯定是访问受限制,那么我们改为通过基于字符串的方式来显式加载,如下:

            using (var ctx = new EfDbContext())
            {
                ctx.Database.Log = Console.WriteLine;

                var customers = ctx.Customers.Include("Orders").ToList();
            };

如上则抛出异常找不到Orders导航属性,是不是到此下结论而定导航属性必须是public呢?访问修饰符除了public,还有protected、internal以及protected internal。通过实践验证若导航属性为private、protected访问修饰符肯定不行,若为internal和protected internal则可以,前提是必须显式配置映射关系,否则也不行,如下:

 protected internal ICollection<Order> Orders { get; set; } = new List<Order>();
 HasMany(p => p.Orders).WithRequired(p => p.Customer).HasForeignKey(k => k.CustomerId);

那么在EF Core是否也和EF 6.x一样呢?我们继续来看看在EF Core中的情况,示例类为Blog和Post,这两个类已经在博客文章多次被用到,就不再给出,我们只关系导航属性访问修饰符的配置,如下:

private ICollection<Post> Posts { get; set; } = new List<Post>();
            using (var context = new EFCoreDbContext())
            {
                var blogs = context.Blogs.Include("Posts").ToList();
            }

此时会同样抛出异常,只不过异常信息大意是Posts不是Blog导航属性的一部分,对于基于字符串的Include方法,导航属性名称要以点分隔开,最终结果还是是找不到Posts导航属性,接下来我们将访问修饰符改为internal看看。

 internal ICollection<Post> Posts { get; set; } = new List<Post>();
            using (var context = new EFCoreDbContext())
            {
                var blogs = context.Blogs.Include(d => d.Posts).ToList();
                //var blogs1 = context.Blogs.Include("Posts").ToList();
            }

此时我们再来显式配置映射关系则好使。

            builder.HasMany(m => m.Posts)
                .WithOne(o => o.Blog);

总结

对于EF和EF Core中通过Include方法进行显式加载具体实现没有去看源码,完全通过实践得到的结论是:无论是EntityFramework还是EntityFramework Core,在关系映射中导航属性不一定必须是public修饰符,也可以为internal和protected internal,但是前提是必须显式配置映射关系,否则将抛出无法找到导航属性异常。

原文地址:https://www.cnblogs.com/CreateMyself/p/9180797.html

时间: 2024-08-06 15:02:55

EntityFramework 6.x和EntityFramework Core关系映射中导航属性必须是public?的相关文章

Hibernate学习笔记(四) — session的产生方式 与 一对多关系映射

一.session的创建 Session是由SessionFactory负责创建的,而SessionFactory的实现是线程安全的,多个并发的线程可以同时访问一个SessionFactory并从中获取Session实例,但Session不是线程安全的. 每次openSession,产生的都是一个新的session,相当于创建一个新的连接.但是有很多时候,并不希望这样.比如在淘宝购物,在付账的一瞬间,至少有三件事情发生,转账,仓库数据变化,购物历史记录.而这三件事有必须在同一事务下.自然我们会联

死去活来,而不变质:Domain Model(领域模型) 和 EntityFramework 如何正确进行对象关系映射?

写在前面 阅读目录: 设计误区 数据库已死 枚举映射 关联映射 后记 在上一篇<一缕阳光:DDD(领域驱动设计)应对具体业务场景,如何聚焦 Domain Model(领域模型)?>博文中,探讨的是如何聚焦领域模型(抛开一些干扰因素,才能把精力集中在领域模型的设计上)?需要注意的是,上一篇我讲的并不是如何设计领域模型(本篇也是)?而是如何聚焦领域模型,领域模型的设计是个迭代过程,不能一概而论,还在路上. 当有一个简单的领域模型用例,完成一个从上而下过程的时候,就需要对领域模型和数据库进行对象关系

EntityFramework 7 更名为EntityFramework Core(预发布状态)

前言 最近很少去学习和探索新的东西,尤其是之前一直比较关注的EF领域,本身不太懒,但是苦于环境比较影响自身的心情,所以迟迟没有下笔,但是不去学习感觉在精神层面缺少点什么,同时也有园友说EF又更新了,要我再写一篇,最终经过思想斗争后,还是花了一点时间去继续探索.本篇比较理论的去分享最近EF进展,后面有时间会继续关注EF团队在EF上的动向,并给出相对应的实例. EF Core 1.0.0 (1)EntityFramework是微软在.NET中推荐使用的数据访问技术,而EntityFramework

EntityFramework Core指定更新导航属性了解一下?

前言 本文来自和何镇汐大哥的探讨,很多时候我习惯于和别人交流过后会思考一些问题,无论是天马行空还是浅薄的想法都会记录下来,或许看到此博文的您能给我更多的思考,与人交流总能收获很多东西,出发点不一样则结论 不一样,思维方式不一样则路径不一样,愿你我共同进步. EntityFramework Core无跟踪视图 首先依然给出本文需要用到的两个实体,如下: public class Blog { public int Id { get; set; } public string Name { get;

EntityFramework Core饥饿加载忽略导航属性问题

前言 .NET Core项目利用EntityFramework Core作为数据访问层一直在进行中,一直没有过多的去关注背后生成的SQL语句,然后老大捞出日志文件一看,恩,有问题了,所以本文产生了,也是有点疑惑,若有知情者,还望告知. EntityFramework Core忽略导航属性 在前面我们已经探讨过利用Serilog日志框架来输出日志,所以对于本节查询日志的输出依然借助Seilog.我们在Startup.cs类中Starup方法中是创建日志实例. Log.Logger = new Lo

EntityFramework 6.x和EntityFramework Core必须需要MultipleActiveResultSets?

前言 本节我们来探讨到底需不需要在连接字符串上加上MultipleActiveResultSets = true ?,若您有更深层次的理解欢迎留下您的脚印. EntityFramework 6.x和EntityFramework Core需要MultipleActiveResultSets? 很多童鞋遇到如下图中错误就立马想到在连接字符串上加上 MultipleActiveResultSets = true ,但是这样真的是最终解决方案么? 下面我们来看一段在EntityFramework 6.

.Net Core使用AutoMapper做对象关系映射

我想很多后端开发者,纠结于如何在Dto及表实体中做属性关系映射,因为真的太繁琐了., ⒈如何使用? 1 Mapper.Initialize(cfg => cfg.CreateMap<UsersInputDto, Users>()); 2 UsersInputDto input = new UsersInputDto() 3 { 4 id = 1, firstname = "fan", lastname = "qi", uname = "f

ASP.NET5实践02:EF7迁移-连接字符串读取-增删改查-关系映射

1.概述 本章重点本应该先从实体关系映射介绍,就像做网页设计先从整体布局开始一样. 最好先基本搞明白实体关系映射到数据表关联关系之后,再研究实体属性或表字段细节. EF7.x和EF6.x区别是很大的.EF7为了迎合NoSql,与以前单一处理关系型数据库映射有一些不同的理念. 在讲这之前,我们先学习EF7迁移和数据库字符串配置读写. 这算准备工作,虽然有些啰嗦,但这是写这篇博客的思路.既然是实践系列,就边体验便写博客! 2.手动迁移 实体类: public class Role { public

Android数据库框架——ORMLite轻量级的对象关系映射(ORM)Java包

Android数据库框架--ORMLite轻量级的对象关系映射(ORM)Java包 事实上,我想写数据库的念头已经很久了,在之前写了一个答题系统的小项目那只是初步的带了一下数据库,数据库是比较强大的,不是我们三言两语就能解决的,我一直想抽个时间自己再过一遍Sqlite和JDBC的,但是,大家也知道,琐事比较多,我们来说一下数据库的框架吧,事实上市面上,我觉得还可以的数据库框架有两个,ORMLite和GreenDao,我以前做的运动类的应用上,就需要存储大量的运动数据,我们最开始是在本地写数据库的