1

У меня есть следующие модели (упрощенный):Как включить унаследованное свойство в «неравномерное» наследование с Entity Framework?

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

Как высказанное «графически»:

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

Теперь я хочу, чтобы загрузить все CartItems и включают в себя данные из класса отеля, если тип CartItem - HotelCartItem.

Вот как я пытаюсь это сделать, но он терпит неудачу с «не объявляет навигационную собственность с именем« Отель ».

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

Если я оставить из .Include("Hotel") собственности Гостиница CartItems гостиничного типа является недействительным.

Мой вопрос:
Есть ли способ обойти это?

ответ

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-объекта.

0

Простая загрузка свойств навигации на подкласс является сложной задачей. Я не нашел другого способа, кроме как загрузить их отдельно. Самый простой способ сделать это регистрирует пользовательский обработчик ObjectMaterialized (только в EF 4.0) на ObjectContext:

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, а второй запрос будет загружать Гостиницы для пунктов корзины, загруженных в первый запрос (в тех же условиях). Ссылки на отели в пунктах корзины должны автоматически устанавливаться, если ваши объекты все еще привязаны к контексту.

Смежные вопросы