使用 Entity Framework ,我有一个类层次结构,它映射到同一个表。类似猫:动物
、狗:动物
、山羊:动物
。
当然,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 是 Dog
,因为此列表是在运行时动态构建的。
基于this post ,我知道 EF 会将其转换为 SQL 查询,其中包含“Discriminator in”语句。所以,这给了我一些希望,我需要的事情可以完成。这:
this.dataRepository.Animals.Where(a => a is **in** houseAnimals);
会很好,但是当然没有这样的语法。
问题是,我可以使用什么语法来实现这一点?我在这里错过了什么吗?这是 EF 中缺少的功能吗?我不可能是唯一一个想要进行此类查询的人。
请不要根据这个示例批评我的方法和执行此查询的需要,因为我只是为了解释我需要什么而对其进行了很多简化。执行 .ToList()
也不是一个选择。
最佳答案
EF 不提供此类开箱即用的功能。但是,在 Expression.TypeIs
的帮助下编写一个动态构建谓词的自定义扩展方法并不难。和 Expression.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);
关于c# - Entity Framework 代码优先 - 从表中选择对象,其中对象的类型位于预定义列表中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38057653/