16

我有 NxN 表,想象一下:

User(id, ...) <- UserAddresses(id, userId, addressId, enabled, ...) -> Addresses(id, ...)

UserAddresses 包含用户和地址的 FK。据我所知,Entity Framework User 创建的 Entity 包含一个 UserAddresses 的集合。Address 包含一个 UserAddresses 的集合,而一个特定的 UserAddress 包含一个对 User 和一个 Address 的引用。

现在我想通过 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 )

但我真正想要的不是为该用户加载所有 UserAddresses ...仅包含启用的那个,设置为 TRUE!

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

4

2 回答 2

16

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 将完全符合您的要求。

如果您真的想将所有内容作为 User 类的一部分返回,则需要分离 result.User,然后更新 result.User.UserAddresses 以指向 result.Addresses。

于 2013-10-15T16:45:16.043 回答
1

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

var foundUser = context.User.Single(x => x.Id == USER_ID);

context.Entry(foundUser).Collection(u =>
u.UserAddresses).Query().Where(userAddress =>
userAddress.Enabled).Load();

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

  1. 如果您将 EF 与延迟加载功能一起使用,则获取您的对象会带来所有关联的集合,这些集合已在您的类中标记为虚拟。因此,通过这样做,您将获得与用户关联的所有 UserAddresses,除非您通过从 User 类的属性中删除关键字来context.User.Single( x => x.id == USER_ID );关闭集合的延迟加载。Virtual

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

PS:

如果以下所有条件都适用,则延迟加载功能将打开:

  1. context.Configuration.LazyLoadingEnabled = true;
  2. context.Configuration.ProxyCreationEnabled = true;
  3. UserAddresses 已在您的 User 类中定义为 Virtual。
于 2014-08-08T00:16:36.900 回答