【问题标题】:Entity framework code first - select objects from table, where type of the object is within a predefined list实体框架代码优先 - 从表中选择对象,其中对象的类型在预定义列表中
【发布时间】:2016-06-28 03:54:56
【问题描述】:

使用实体框架,我有一个类层次结构,它们映射到同一个表。类似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 查询。所以,这给了我一些希望,我需要做的事情。这个:

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

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

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

请不要根据这个示例对我的方法和执行此查询的需要进行解释,因为我已经简化了很多只是为了解释我需要什么。做.ToList() 也不是一种选择。

【问题讨论】:

  • 如果我是你,我会非常厌倦 Discriminator 列,只有在你真的需要时才使用它们。 SQL 有关系——主键和外键——尝试使用这种继承映射可能会给你带来各种各样的问题
  • 我没有明确地使用鉴别器列。
  • 好的,让我换个说法 - 我会非常厌倦在 SQL 中使用 C# 对象继承映射。
  • 这是 EF 代码首先工作的默认方式。包管理器控制台为我生成 SQL 脚本,它决定为我的类 + 鉴别器使用单个表。我没有资格批评它;)

标签: c# entity-framework


【解决方案1】:

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&lt;Animal&gt;,则用法为:

this.dataRepository.Animals.OfType(houseAnimals);

【讨论】:

  • 我知道我应该避免像 +1 这样的 cmets,但我不得不说这是一个令人印象深刻的解决方案,它对我有用。
  • 仓库实际上暴露了IDbSet&lt;Animal&gt; Animals。我在使用您的代码时遇到问题 - no overload for method 'OfType' takes 1 argument
  • OfType 有一个参数是答案中的方法。确保扩展方法在您需要的地方可见。即using {the namespace containing above class};.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-17
  • 1970-01-01
  • 2013-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多