Linq: методы расширения IQueryable работают на DBSet, но не на ICollection - PullRequest
0 голосов
/ 20 ноября 2018

У меня есть проект с пакетом EntityFramework 6.1.0

, и я работаю с моделью DB-First

Некоторые объекты модели были расширены следующим образом:

public interface IVersionable{
int VersionId{get;set;}
}
public interface IEditable{
bool IsEditable{get;set;}
}
public interface IFullFeatures:IVersionable,IEditable{}
public partial EntityOne:IFullFeatures{
   //This is the extension partial class for the auto-generated model class EntityOne that already has interface properties
}
public partial EntityTwo:IFullFeatures{
   //This is the extension partial class for the auto-generated model class EntityTwo that already has interface properties
}

Автоматически сгенерированные классы EntityOne и EntityTwo имеют все свойства, требуемые IFullFeatures, а для автоматически сгенерированного файла EntityTwo у нас есть эта ICollection:

public virtual ICollection<EntityOne> EntityOne {get;set;}

Наконец, у меня есть метод расширения:

public static class FeaturesExtensionMethod{
     public static IQueryable<T> FilterEditable<T>(this IQueryable<T> source) where T:class,IEditable{
         return source.Where(s=>s.IsEditable);
     }
     public static IQueryable<T> FilterVersion<T>(this IQueryable<T> source, int versionId) where T:class,IVersionable{
         return source.Where(s=>s.VersionId==versionId);
     }
     public static IQueryable<T> FullFilter<T>(this IQueryable<T> source, int versionId) where T:class,IVersionable{
         return source.FilterEditable().FilterVersion(versionId);
     }
}

Затем, когда во время выполнения я выполняю это:

var everyEntitiTwo=ctx.EntityTwo.FullFilter(4).ToList();

нет проблем, он работает нормально и фильтрует ... но когда во время выполнения я выполняю это вместо этого:

var test= ctx.EntityTwo.Include("EntityOne").Select(et=>et.EntityOne.AsQueryAble().FullFilter(4)).ToList()

Я получаю эту ошибку:

LINQ to Entities не распознает метод метода FullFilter, и этот метод нельзя преобразовать в выражение хранилища.

Итаквопрос в том, что не так в моих методах расширения?Почему я получаю эту ошибку во втором случае, а не даже в первом?

Спасибо.

ОБНОВЛЕНИЕ

Благодаря Джону Ханне я вдохновилсяк этому альтернативному способу достижения того же результата:

Я создал «прокси-класс» для получения фильтра, потому что Expression > строго типизирован, и мне нужно что-то более общее:

public static FilterProxies{
    public static GetProxiedFilter<T>(int versionId, bool onlyEditable) where T: class, IFullFeatures{
       Expression<Func<T,bool>> filteredExp
       if(onlyEditable){
          filteredExp=(iff=>iff.VersioneId==versionId&&iff.IsEditable);
       }
       else{
          filteredExp=(iff=>iff.VersioneId==versionId); 
       }
       return filteredExp;
   }
}

Затем, при использовании:

var filter=FilterProxies.GetProxiedFilter<EntityOne>(4,true);
var test= ctx.EntityTwo.Include("EntityOne").Select(et=>et.EntityOne.AsQueryAble().Where(filter)).ToList()

Надеюсь, что буду полезен при обновлении этого поста, спасибо Джону за то, что он вдохновил меня применить это решение

Ответы [ 2 ]

0 голосов
/ 20 ноября 2018

EF не может перевести метод FullFilter в SQL, так как вы используете LINQ to Entities.Возможно, вам придется использовать Linq to Objects

ctx.EntityTwo.ToList () перед вашим методом, чтобы он сначала получил список вашего объекта, а затем выполнил ваш метод с использованием этого списка, выполнив то, что вы делаете LINQ ToОбъекты

0 голосов
/ 20 ноября 2018
ctx.EntityTwo.FullFilter(4).ToList();

Получается немедленно превращается в

ctx.EntityTwo.Where(s => s.IsEditable).Where(s => s.VersionId == 4).ToList();

Что, конечно, может обрабатывать Entity Framework.

var test= ctx.EntityTwo.Include("EntityOne").Select(et=>et.EntityOne.AsQueryAble().FullFilter(4)).ToList()

Поскольку использование вашегоЗапрашиваемые расширения являются в запросе и действуют на другой тип запрашиваемого запроса, вызовы методов являются частью выражения, переданного в Entity Framework, и он не знает, что делает FullFilter(), и задыхается от этого.точка.

...