C# LINQ实体包括+;何处方法

C# LINQ实体包括+;何处方法,c#,.net,linq,entity-framework,include,C#,.net,Linq,Entity Framework,Include,我有NxN表,想象一下: 用户(id…)地址(id…) UserAddresses包含FK到用户和到地址。 据我所知,EntityFramework用户创建的实体包含一个指向UserAddresses的集合。地址包含指向UserAddresses的集合,特定UserAddress包含指向User和指向一个地址的一个引用 现在我想由linq进行下一个查询。 对于特定的用户id,仅获取启用标志设置为true的userAddresses。 对于特定的用户id,userAddresses可以包含多个条目

我有NxN表,想象一下:

用户(id…)地址(id…)

UserAddresses包含FK到用户和到地址。 据我所知,EntityFramework用户创建的实体包含一个指向UserAddresses的集合。地址包含指向UserAddresses的集合,特定UserAddress包含指向User和指向一个地址的一个引用

现在我想由linq进行下一个查询。 对于特定的用户id,仅获取启用标志设置为true的userAddresses。 对于特定的用户id,userAddresses可以包含多个条目,但仅为此特定用户设置一个条目

我可以做的查询是:

context.User.Include( x => x.UserAddresses )
            .Include( x => x.UserAddresses.Select(y => y.Address) )
            .Single( x => x.id == USER_ID )
但我真正想要的不是加载该用户的所有用户地址。。。仅包含已启用、设置为TRUE的选项


有人可以帮我做这个查询吗?

在EF中无法部分加载关联属性。尝试选择匿名类型以仅获取所需内容:

var result = context.User
   .Where(u => u.Id == userId)
   .Select(u => new {
       Addresses = u.UserAddresses.Select(ua => ua.Address)
            .Where(a => a.Enabled),
       User = u // if you need this as well 
   })
   .Single();
这不会加载result.User.UserAddresses,但result.Addresses将完全符合您的要求


如果确实希望将所有内容作为用户类的一部分返回,则需要分离result.User,然后更新result.User.UserAddresses以指向result.Addresses。

另一种选择是使用
Load()
而不是
Include()

请记住,在某些情况下,
Load()
方法可能会被EF忽略:

  • 如果将EF与延迟加载功能一起使用,则获取对象会带来类中标记为虚拟的所有关联集合。因此,通过执行
    context.User.Single(x=>x.id==User\u id)
    除非通过从用户类的属性中删除
    Virtual
    关键字来关闭集合的延迟加载,否则您将获得与该用户关联的所有用户地址

  • 如果在程序中添加/删除UserAddresses集合,并调用context.SaveChanges();在不处理上下文的情况下,下次加载用户对象时,UserAddresses集合将从EF上下文缓存而不是从DB(您的最新更改)加载。在这种情况下,在从上下文中获取用户之前,您需要处理您的上下文并实例化一个新的上下文。例如,如果您的用户在UserAddresses集合中有5项,并且您禁用了其中一项(
    item.Enabled=false
    ),然后调用
    context.SaveChanges()
    ,而不处理您的上下文,下次当您从同一上下文中获取用户对象时,它的集合中已经有5个来自上下文缓存的项,它会忽略您的
    Load()
    方法

  • 附言:

    如果应用了以下所有条件,则延迟加载功能将启用:

  • context.Configuration.LazyLoadingEnabled=true
  • context.Configuration.ProxyCreationEnabled=true
  • UserAddresses已在用户类中定义为虚拟

  • 您使用的是哪种
    包含
    ?据我所知,
    System.Data.Objects.ObjectQuery的
    Include
    方法只接收字符串的一个参数?@KingKing我已经做了一个扩展方法,将lambda表达式格式化为字符串,并将其传递给“native”ObjectQuery Include方法。如果是这样,您的问题的答案是
    不可能
    Include
    功能不太强大,在包含之前无法执行任何
    筛选
    。我需要返回包含所有相关内容的用户实体,但不是所有集合都已映射。。所以我认为匿名类型是不对的:/@goncaloRD:不幸的是,
    中的
    条件不可能使用
    Include
    。这是你最好的选择。@ChaseMedallion谢谢,这正是我需要的。查询完成得非常完美,EF对象按照我想要的方式映射。我创建了一个类型来对我的对象进行典型化,以便在我的业务层中使用。
    var foundUser = context.User.Single(x => x.Id == USER_ID);
    
    context.Entry(foundUser).Collection(u =>
    u.UserAddresses).Query().Where(userAddress =>
    userAddress.Enabled).Load();