2016-05-12 7 views
0

Я пытаюсь создать функцию, которая в общем случае загружает связанные дочерние объекты с фильтром.Entity Framework, общая загрузка связанных объектов с условием where

Все мои объекты являются производными от моего собственного базового класса «BusinessObject»

public abstract class BusinessObject : BaseObject, IBaseObject, ILocalObject 
{ 
    [Browsable(false)] 
    [Key] 
    public int ID { get; set; } 

    [Browsable(false)] 
    public int? HqID { get; set; } 

    private bool _deleted; 
    [Browsable(false)] 
    public bool Deleted 
    { 
     get { return _deleted; } 
     set { CheckPropertyChanged(ref _deleted, value); } 
    } 
} 

Я создал следующую функцию, которая при поставке предприятие будет загружать все соответствующие дочерние объекты. При определении моих сущностей все дочерние коллекции помечены моим собственным атрибутом «EntityChildCollectionAttribute», поэтому я могу легко найти коллекции, которые я хочу загрузить.

public virtual void OnLoadEntityChildren(object entity) 
    { 
     var propNames = entity.GetPropertyNames(); 
     foreach (var propName in propNames.Where(propName => entity.PropertyHasCustomAttribute(propName, typeof(EntityChildCollectionAttribute)))) 
     { 
      MyData.Entry(entity).Collection(propName).Load();        
     } 
    } 

Это прекрасно работает! Моя проблема возникает, когда я хочу фильтровать дочернюю коллекцию.

В этом случае я хочу только загружать дочерние объекты, где Deleted == false.

Не могу решить, как это сделать!

У меня было много попыток и замена MyData.Entry (entity) .Collection (propName) .Load(); с

MyData.Entry(entity).Collection(propName).Query().Cast<BusinessObject>().Where(x=>x.Deleted.Equals(false)).Load(); 

компилируется, но затем я получаю сообщение об ошибке;

«Невозможно передать тип« FmOrderProcessing.Entities.OpDocumentDetail »для ввода« FwBaseEntityFramework.BusinessObject ». LINQ to Entities поддерживает только листинг примитивных или перечисляемых типов EDM».

Любые Помощь/Указатели/ответы будут с благодарностью приняты

Спасибо заранее

Lance

+0

Иногда просто писать чистый SQL это лучший ответ .... Если это становится слишком сложным в EF, написать sproc. –

+0

EF не знает 'BusinessObject'. Это не сопоставленный тип. –

+0

Кстати, мне интересно, почему вы не используете 'Include'. Ваш код загружает дочерние коллекции для каждого родителя отдельно, также известный как анти-n + 1. –

ответ

2

Я реализует «Soft Delete» шаблон, который означает, что записи в базе данных помечаются как удаленные а не удаляться (для целей аудита и репликации).

Все объекты получены из базового определения с помощью свойства bool Deleted.

Я нашел ответ здесь:

https://www.nuget.org/packages/EntityFramework.DynamicFilters

Этот пакет позволяет определение глобальных фильтров в контексте данных. Я исправил свою проблему одной строкой кода в переопределении OnModelCreating.

modelBuilder.Filter("Deleted", (IBaseObject d) =>d.Deleted, false); 

Функция фильтра применяется глобально к любой сущности, представляющей (в моем случае) интерфейс IBaseObject.

Я надеюсь, что это помогает любому телу еще с подобным вопросом

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