C# 实体框架代理创建
我见过不少解决问题的方法,这些方法总是和我的类似。但没有一个能特别满足我的需求 我有以下设置:C# 实体框架代理创建,c#,entity-framework,C#,Entity Framework,我见过不少解决问题的方法,这些方法总是和我的类似。但没有一个能特别满足我的需求 我有以下设置: 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
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; }
}
公共类用户
{
公共Int32 Id{get;set;}
公共字符串名称{get;set;}
公共虚拟列表电话簿{get;set;}
}
公共类电话簿
{
公共Int32 Id{get;set;}
公共虚拟Int32用户标识{get;set;}
公共虚拟用户用户{get;set;}
公共字符串标题{get;set;}
公共虚拟列表编号{get;set;}
}
公共类电话号码
{
公共Int32 Id{get;set;}
公共字符串Num{get;set;}
公共虚拟Int32 PhoneBookId{get;set;}
公共虚拟电话簿电话簿{get;set;}
}
现在我完全可以提问了。问题在于循环引用
假设我想为id=1的用户选择每个电话簿
我的问题是
context.phonebook.Where(x=>x.UserId==1)
这将加载用户和每个电话号码。
我可以关闭代理,我只能得到电话簿(没有号码,没有用户)
如果我也想获取每个电话号码,但不想获取用户,该怎么办?
此外,我还必须确保获取phonenumber对象并不意味着获取与该号码相关的电话簿。
我需要代理只走一条路。向下而不是向上。首先,您的外键ID不需要是虚拟的。只能对导航属性(或其他实体类型属性)使用
virtual
:外键不是导航属性,它只是一个整数
现在,您的问题实际上与代理无关,而是与延迟加载有关(代理默认启用延迟加载,这就是您关心代理的原因,但这不是必需的)
如果只想加载指定的实体,请禁用延迟加载并执行快速加载:
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
});
加载相关数据的三种方法:@MarianneMarkwardt不,你不是。外键只是整数。导航属性指向其他实体。它们会自动填充外部实体id,但这不是“导航属性”。要加载另一个级别,可以使用字符串语法(
.Include(“Number.OtherLevel”)
,或者lambda语法:对于导航属性:Include(s=>s.Number.OtherProperty)
,或者对于集合:Include(s=>s.Number.Select(t=>t.CollectionItem))
。这里介绍了所有内容:(查找“急切地加载多个级别”)好的。非常感谢Jcl。我标记了你的答案。虽然这个问题可能属于另一个主题,但你能告诉我为什么context.phonebooks.Where(x=>x.id==1)可以工作,但是context.phonebooks.Include(x=>x.title)由于错误而失败”指定的包含路径无效。EntityType..未声明名为“Title”的导航属性。“Include”用于加载相关实体。“Title”是字符串类型的属性,而不是相关实体(导航属性或集合)是..我刚按enter键时意识到这一点..再次感谢Jcl。祝您愉快:)