首先是实体框架代码 - 从表中选择对象,其中对象的类型在预定义列表中

时间:2016-06-27 15:19:30

标签: c# entity-framework

使用Entity Framework,我有一个类层次结构,它们映射到同一个表。类似于Cat : AnimalDog : AnimalGoat : Animal

当然,EF内部使用Discriminator列来处理它们。

现在,我想写一些类似的东西:

var houseAnimals = new List<Type>(new [] { typeof(Cat), typeof(Dog) });
this.dataRepository.Animals.Where(a => houseAnimals.Contains(a.GetType()));

当然,这不会起作用,因为LINQ-to-SQL不支持.GetType()。但是,这可行:

this.dataRepository.Animals.Where(a => a is Cat);

我不想a is Cat || a is Dog,因为此列表是在运行时动态构建的。

基于this post,我了解EF会将其转换为SQL查询,其中包含&#39; Discriminator in&#39;声明。所以,这给了我一些希望,我需要做的事情。这样:

this.dataRepository.Animals.Where(a => a is **in** houseAnimals);

会很好,但当然没有这样的语法。

问题是,我可以使用什么语法来实现这一目标?我在这里错过了什么吗?这是EF中缺少的功能吗?我不可能是唯一一个想要进行此类查询的人。

基于这个例子,请不要将我的方法和执行此查询的需要放在一边,因为为了解释我的需要,我已经简化了很多。做.ToList()也不是一种选择。

1 个答案:

答案 0 :(得分:2)

EF不提供开箱即用的此类功能。但是编写一个自定义扩展方法并不难,在Expression.TypeIsExpression.OrElse的帮助下动态构建谓词:

public static class QueryableExtensions
{
    public static IQueryable<T> OfType<T>(this IQueryable<T> source, IEnumerable<Type> types)
    {
        var parameter = Expression.Parameter(typeof(T), "a");
        var body = types
            .Select(type => Expression.TypeIs(parameter, type))
            .Aggregate<Expression>(Expression.OrElse);
        var predicate = Expression.Lambda<Func<T, bool>>(body, parameter);
        return source.Where(predicate);
    }
}

假设您的存储库返回IQueryable<Animal>,则使用情况为:

this.dataRepository.Animals.OfType(houseAnimals);