实体框架一对一关系
Posted
技术标签:
【中文标题】实体框架一对一关系【英文标题】:Entity Framework one-to-one relationships 【发布时间】:2017-10-03 15:09:38 【问题描述】:我在理解如何使用 Entity Framework Core 为 Web API 设置一对一关系时遇到了一些问题。
考虑以下对象:
public class Car
[JsonIgnore]
public Int32 CarId get; set;
public virtual Horn Horn get; set;
public virtual ICollection<Wheel> Wheels get; set;
public class Horn
[JsonIgnore]
public Int32 HornId get; set;
public Sound Sound get; set;
public class Sound
// some other props
当我在我的存储库中执行查询时,默认情况下会排除一对多,除非我使用 .Include()
,但是,对于一对一属性,默认情况下会在我序列化时包含它们。
例如它变得非常混乱,因为我查询了一辆车,它在 JSON 响应中返回了它的所有子组件。
我可以设置car.Horn = null
等,但对于复杂的对象,这似乎很难维护。我希望它像.Include()
一样工作,但默认情况下被排除在外(如果我确实想查询完整对象)。
编辑:注意,这个问题是递归的,汽车拉响喇叭从而拉响声音。在像用户表这样的真实示例中,除非专门取消子属性,否则序列化时自动拉入的数据非常巨大。
编辑2:
这是一个存储库调用示例,默认情况下会返回所有一对一属性:
var group = _context.Car.Include(c =>
c.Wheels).SingleOrDefault(u => u.CarId == id);
请注意,对于多对一,包含按预期工作,但即使删除了包含,此查询也会递归返回所有一对一的子对象。
似乎在 EF CORE 2.1 中引入了某种类型的延迟加载
【问题讨论】:
显示您的实体配置 - 您是否使用复杂类型、表格拆分? 你使用的是 EF Core 还是? 我正在使用 EF Core,简单的实体与主键上的关系。 最新的 EFC 2.0 中不会发生这种情况。你用的是什么EFC版本?您还需要提供minimal reproducible example。 我正在使用 EF CORE 2.0: 【参考方案1】:这篇文章应该给你一个提示。 https://msdn.microsoft.com/en-us/library/jj574232(v=vs.113).aspx 主要是:
关闭延迟加载以进行序列化
延迟加载和序列化不能很好地混合,如果你不是 小心,您最终可能会查询整个数据库,因为 延迟加载已启用。大多数序列化程序通过访问每个 类型实例的属性。属性访问触发惰性 加载,因此更多的实体被序列化。在那些实体属性上 被访问,甚至更多的实体被加载。这是一个很好的做法 在序列化实体之前关闭延迟加载。以下 部分展示了如何做到这一点。
编辑: 这是为所有实体禁用延迟加载的方法。但请注意,您必须通过多种方式实现此目的,因此请查看文章中的其他选项...
public class YourContext : DbContext
public YourContext()
this.Configuration.LazyLoadingEnabled = false;
【讨论】:
这不是真正的答案。展示你如何关闭它,然后它可能是一个有效的答案。 EF Core 不支持延迟加载 是的,这仅对经典 EF 有效 太糟糕了,这在 EF Core 中不起作用 - 这与我正在寻找的类似。当它是一个包含许多一对一表的较大表(例如“用户”表)时,这个问题会变得更糟。除非无效,否则即使子表也会从这些表中引入一对一的子关系,因此它是递归的!【参考方案2】:上下文映射
modelBuilder.Entity<SessionFeedbackModel>(entity =>
entity.HasOne(s => s.Session).WithOne(p => p.Feedback)
.HasForeignKey<SessionFeedbackModel>(s => s.SessionId).OnDelete(DeleteBehavior.Restrict);
);
modelBuilder.Entity<SessionQuestionModel>(entity =>
entity.HasOne(e => e.SessionResult).WithOne(e => e.SessionQuestion)
.HasForeignKey<SessionQuestionResultModel>(e => e.SessionQuestionId)
.OnDelete(DeleteBehavior.Restrict);
);
型号
public class SessionQuestionResultModel
public int Id get; set;
public int SessionQuestionId get; set;
public SessionQuestionModel SessionQuestion get; set;
public class SessionFeedbackModel
public int Id get; set;
public int SessionId get; set;
public SessionModel Session get; set;
EF Core 1.x 或 2.x 不太支持或根本不支持 1 对 1,但可以通过这种方式完成,这对于 EF 6.x.x 将完全不同
【讨论】:
以上是关于实体框架一对一关系的主要内容,如果未能解决你的问题,请参考以下文章
实体框架代码优先关系 - 如何定义两个对象之间的关系:两个实体之间的可选一对一