使用Code-first Entity Framework筛选多个派生类

9
假设我有一个名为User的对象,它有两个派生实体StudentTeacher。我使用了TPH方法,因此我的类中实际上没有任何属性可以告诉我谁是老师或学生。
我有两个布尔值,应该允许我加载学生或老师,如下所示:
//IQueryable<User>
var query = userRepository.GetUsers();

//Type filtering
if (searchModel.IsStudent)
{
    query = query.OfType<Student>();
}
if (searchModel.IsTeacher)
{
    query = query.OfType<Teacher>();
}

当两个条件都为真时,这段代码尝试进行求值时会出现以下错误:DbIsOfExpression 需要一个表达式参数,其多态结果类型与类型参数兼容。 我已经查看了一些 Stack Overflow 上的答案,但它们都是针对一种类型的过滤。
然后,我想做类似于以下的事情(粗略编码):
if(query.ToList().FirstOrDefault() is Student)
{
     print "student";
}

映射关系如下:
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<User>()
                    .Map<Teacher>(m => m.Requires("UserType").HasValue("Teach"))
                    .Map<Student>(m => m.Requires("UserType").HasValue("Stu"))
                    .Map<Staff>(m => m.Requires("UserType").HasValue("Staff"));
    }

你能展示一下你的类吗?你是使用Code First吗?你有什么映射代码可以分享吗? - Wouter de Kort
@LadislavMrnka 我添加了查询类型。 - Shawn Mclean
如果你想要“加载学生教师”,为什么要有两个布尔值都可以为真?将该情况视为不可行,问题就解决了。即使没有这个异常,结果也总是为空,因为在你的模型中,用户不能同时是StudentTeacher。如果你想要同时过滤两者,你需要一个逻辑OR而不是链接查询(表示逻辑AND)。 - Slauma
@Slauma 我想把它们结合起来,这样两者都可以成立,你能给一个代码片段的例子吗? - Shawn Mclean
如果 (searchModel.IsStudent && !searchModel.IsTeacher) 则查询 = 查询.OfType<Student>(); 否则如果 (searchModel.IsTeacher && !searchModel.IsStudent) 则查询 = 查询.OfType<Teacher>(); - Slauma
2个回答

5

试试这个。至少对于EF 5有效。

IQueryable<User> Filter(this IQueryable<User> query, 
    bool includeTeacher, bool includeStudent)
{

  return query.Where(x => includeTeacher && x is Teacher
                || includeStudent && x is Student);
}

1

这不太美观,但它能满足你的需求:

if (searchModel.IsStudent && searchModel.IsTeacher) 
{
    var result = context.Users.OfType<Teacher>()
                        .Cast<User>()
                        .Union(context.Users.OfType<Student>());
}

而且它只需要运行一个查询!!:)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接