1

我有以下模型(简化):

abstract class CartItem { EntityReference<Cart> Cart; }
class HotelCartItem : CartItem { EntityReference<Hotel> Hotel; }
class TransferCartItem : CartItem { }
class Hotel { }

如“以图形方式”表达的:

CartItem
|<- HotelCartItem
|   |-> Hotel
|
|<- TransferCartItem

现在,如果 CartItem 的类型是 HotelCartItem,我想加载所有 CartItem 并包含来自 Hotel 类的数据。

这就是我试图这样做的方式,但它失败了“没有声明名为'Hotel'的导航属性”。

var q = from cartitems in context.CartItems
            .Include("Hotel")
        where cartitems.CART_ID == CartID
        select cartitems;

如果我遗漏了.Include("Hotel")Hotel 类型的 CartItems 的 Hotel 属性为空。

我的问题:
有没有办法解决这个问题?

4

2 回答 2

0

在子类上急切加载导航属性是很棘手的。除了单独加载它们之外,我还没有找到任何其他方法。最简单的方法是在 ObjectContext 上注册自定义 ObjectMaterialized 处理程序(仅在 EF 4.0 中):

context.ObjectMaterialized += RegisterEagerLoadingStrategies;

处理程序方法如下所示:

private static void RegisterEagerLoadingStrategies(object sender, ObjectMaterializedEventArgs e)
{
  var context = (ObjectContext)sender;

  var cartItem = e.Entity as HotelCartItem;
  if (cartItem != null)
  {
    context.LoadProperty(cartItem, o => o.Hotel); 
  }
}

这个解决方案有 N + 1 个问题。N + 1 意味着如果您的主查询返回 N HotelCartItems 您将在数据库中执行 N + 1 个查询(每个 LoadProperty 调用附加查询)。此外,每个加载的实体都会调用此方法(不仅针对 HotelCartItem)。所以这个解决方案对于加载大量实体​​来说真的很糟糕。

从相关实体加载导航属性的另一种方法是将您的查询分成两个查询。第一个查询将加载 CartItems,第二个查询将加载第一个查询中加载的购物车项目的 Hotels(相同条件)。如果您的实体仍附加到上下文,则应自动设置对购物车项目中酒店的引用。

于 2010-11-25T13:06:04.813 回答
0

我最终将查询分成几个部分:

  1. 加载父项目,一个“购物车”。
  2. 对于我得到的每种不同类型(HotelCartItem 和 TransferCartItem),我在数据库中查询了一组只有该类型:
private IQueryable<T> GetCartItemQuery<T>(Guid CartID) where T : CartItem
{
    if (typeof(T) == typeof(HotelCartItem))
    {
        var q = from ci in db.CartItems.OfType<T>()
                    .Include("Hotel")
                where ci.CART_ID == CartID
                select ci;
        return q;
    }
    else
    {
        var q = from ci in db.CartItems.OfType<T>()
                where ci.CART_ID == CartID
                select ci;
        return q;
    }
}

调用它:

var hotels = GetCartItemQuery<HotelCartItem>(CartID);
var transfers = GetCartItemQuery<TransferCartItem>(CartID);

3. 将 CartItems 添加到 Cart 对象的集合中。

于 2011-02-15T13:45:01.937 回答