C# 实体框架代码优先-从表中选择对象,其中对象的类型在预定义列表中
使用实体框架,我有一个类的层次结构,这些类映射到同一个表。比如猫:动物,狗:动物,山羊:动物 当然,EF在内部使用鉴别器列来处理它们 现在,我想写一些类似的东西:C# 实体框架代码优先-从表中选择对象,其中对象的类型在预定义列表中,c#,entity-framework,C#,Entity Framework,使用实体框架,我有一个类的层次结构,这些类映射到同一个表。比如猫:动物,狗:动物,山羊:动物 当然,EF在内部使用鉴别器列来处理它们 现在,我想写一些类似的东西: var houseAnimals = new List<Type>(new [] { typeof(Cat), typeof(Dog) }); this.dataRepository.Animals.Where(a => houseAnimals.Contains(a.GetType())); 我不想做一个is C
var houseAnimals = new List<Type>(new [] { typeof(Cat), typeof(Dog) });
this.dataRepository.Animals.Where(a => houseAnimals.Contains(a.GetType()));
我不想做一个is Cat | | is Dog,因为这个列表是在运行时动态构建的
基于,我了解到EF将把它转换为SQL查询,该查询具有“Discriminator in”语句。所以,这给了我一些希望,我所需要的可以做到。这:
this.dataRepository.Animals.Where(a => a is **in** houseAnimals);
这很好,但是当然没有这样的语法
问题是,我可以使用什么语法来实现这一点?我是不是遗漏了什么?这是EF中缺少的功能吗?我不可能是唯一一个想做这种询问的人
基于这个例子,请不要把我的方法和进行这个查询的需要简单化,因为我已经简化了很多,只是为了解释我需要什么。Doing.ToList也不是一个选项。EF不提供这种现成的功能。但编写一个自定义扩展方法并不难,它可以借助和动态构建谓词,如下所示:
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);
}
}
如果我是你,我会对鉴别器列感到非常厌倦,并且只在你真的需要的时候才使用它们。SQL有关系-主键和外键-尝试使用这种继承映射可能会导致各种问题。我不显式使用鉴别器列。好的,让我重新表述一下-我会非常厌倦在SQL中使用C对象继承映射。这是EF代码首先工作的默认方式。包管理器控制台为我生成SQL脚本,它决定为我的类和鉴别器使用一个表。我没有资格批评它;我知道我应该避免像+1这样的评论,但我必须说这是一个令人印象深刻的解决方案,它对我很有效。我在使用您的代码时遇到问题-没有方法“OfType”的重载包含1个参数。答案中的方法是带有一个参数的OfType。确保扩展方法在需要它的地方可见。i、 e.使用{包含上述类的命名空间};。
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);
}
}
this.dataRepository.Animals.OfType(houseAnimals);