实体框架代理制造痛苦

本文关键字:制造 痛苦 代理制 代理 框架 实体 | 更新日期: 2023-09-27 18:29:19

我看到了很多与我相似的问题解决方案。但没有一个能特别满足我的需求。

我有以下设置:

public class User
{
    public Int32 Id { get; set; }
    public String Name { get; set; }
    public virtual List<PhoneBook> Phonebooks { get; set; }
}
public class PhoneBook
{
    public Int32 Id { get; set; }
    public virtual Int32 UserId { get; set; }
    public virtual User User { get; set; }
    public String Title { get; set; }
    public virtual List<PhoneNumber> Number { get; set; }
}
public class PhoneNumber
{
    public Int32 Id { get; set; }
    public String Num { get; set; }
    public virtual Int32 PhoneBookId { get; set; }
    public virtual PhoneBook PhoneBook { get; set; }
}

现在我完全可以查询了。问题在于循环引用。

假设我想为id为1的用户选择每个电话簿我的问题是context.phonebook.Where(x=>x.UserId == 1)这将加载用户和每个电话号码。我可以关闭代理,只会得到电话簿(没有号码,没有用户)。

如果我也想得到每个电话号码,但不想得到用户,该怎么办?此外,我必须确保获得电话号码对象并不意味着它也获得了与该号码相关的电话簿。我需要代理只能走一条路。顺着梯子往下走,不要往上走。

实体框架代理制造痛苦

首先,您的外键id不需要是virtualvirtual仅用于导航属性(或其他实体类型属性):外键不是导航属性,它只是一个整数。

现在你的问题实际上与代理无关,而是与延迟加载有关(代理默认启用延迟加载,这就是为什么你关心它们,但这不是必要的)。

如果您只想加载指定的实体,请禁用延迟加载并执行热切加载:

context.Configuration.LazyLoadingEnabled = false;
// Load phonebook entries and users matching your id
var result = content.phonebook
                .Include(x => x.Number)
                .Include(x => x.User)
                .Where(x => x.UserId == 1); 
// Load only phonebook entries without users    
var result2 = content.phonebook
                .Include(x => x.Number)
                .Where(x => x.UserId == 1); 

那个简单的

PS:代理比延迟加载(如更改跟踪等)更有优势。如果你的问题是延迟加载,请关闭延迟加载,而不是代理

在这种情况下,造成痛苦的不是代理创建,而是懒惰加载尽一切办法禁用它,并包括您想要的导航属性或特别投影您的结果:

context.phonebook
  .Include(x=> x.Number)
  .Where(x=>x.UserId == 1);
// or
context.phonebook
  .Where(x=>x.UserId == 1)
  .Select(x=> new{ 
       Phonebook = x,
       Number = x.Number
       });