c# - Entity Framework 代码优先 - 从表中选择对象,其中对象的类型位于预定义列表中

标签 c# entity-framework

使用 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/

相关文章:

c# - Windows 上的 Java 需要记录 CPU 负载和类似的操作系统特定性能信息

c# - WPF 刷新绘图是否类似于 Windows 窗体?

php - Doctrine,如何左连接一个未生成的实体?

c# - 如何映射具有延迟加载属性的实体(不会导致它们加载)?

c# - 实现 IAsyncEnumerable 的空 IQueryable

c# - 为什么结构需要装箱?

c# - 请求被中止 : Could not create SSL/TLS secure channel - SecurityProtocol behavior

c# - 迭代上下文类型的查询结果时发生异常。连接已关闭

c# - 排队 EF 查询

c# - Entity Framework 加载相关实体