简体   繁体   English

EF 6,LINQ如何在内部创建包含条件参数的位置

[英]EF 6, LINQ how to create where inside include with conditional parameter

I have 4 tables 我有4张桌子

tblTraining
-----------
ID
Name

tblQuestion
----------
ID
Name
Active (true / false)
(FK) TrainingID

tblAnswer
----------
ID
Name
Active (true / false)
(FK) QuestionID

tblEmployeeTraining
-------------------------
ID
(FK) EmployeeID
(FK) TrainingID

Each Training has many Questions, and each Question has many Answers. 每个培训都有很多问题,每个问题都有很多答案。 I also have tblEmployeeTraining to store every employee that do the related training. 我也有tblEmployeeTraining来存储每位进行相关培训的员工。

I wanna to get the training object by training ID, but I have conditional parameter to include the Question or EmployeeTraining. 我想通过培训ID获取培训对象,但是我有条件参数包括Question或EmployeeTraining。

So here I call my query: 所以在这里我打电话给我的查询:

GetTraining(dbContext, ID: 1, includeEmployeeTrainings: true, includeQuestions: false);

here my GetTraining Function: 这是我的GetTraining函数:

public static TrainingCourse GetTraining(dbContext, int ID = 0,
        bool includeEmployeeTrainings = false, bool includeQuestions = false)
    {
        try
        {
            IQueryable<tblTraining> training = (
                    from tc in dbContext.tblTraining
                    select tc);

            //where 
            if (ID != 0) training = training.Where(tc => tc.ID == ID);

            //include
            var includeQuestionQuery = includeQuestions ? training.Select(tc => new
            {
                Questions = tc.tblQuestions.Where(qq => qq.IsActive == true),
                Answers = tc.tblQuestions.Select(qq => qq.tblAnswers.Where(qa => qa.IsActive == true)),
            }) : null;

            var includeEmployeeTrainingsQuery = includeEmployeeTrainings ? training.Select(tc => new
            {
                EmployeeTrainings = tc.tblEmployeeTrainings.AsEnumerable()
            }) : null;

            training = training.Select(tc => new
            {
                tc,
                includeQuestionQuery,
                includeEmployeeTrainingsQuery,
            }).AsEnumerable().Select(tc => tc.tc).AsQueryable();

            return training.FirstOrDefault();
        }
        catch
        {
            throw;
        }
    }

the above code will work perfectly if I call like this 如果我这样调用,上面的代码将完美地工作

GetTraining(dbContext, 1, includeEmployeeTrainings: true, includeQuestions: true);

but get an error if I call like this 但是如果我这样打来就会出错

GetTraining(dbContext, 1, includeEmployeeTrainings: false, includeQuestions: true);

Unable to create a null constant value of type 'System.Linq.IQueryable 1[[<>f__AnonymousType2 1[[System.Collections.Generic.IEnumerable`1[[.....]]'. 无法创建类型为'System.Linq.IQueryable 1[[<>f__AnonymousType2 1 [[System.Collections.Generic.IEnumerable`1 [[.....]]]”的空常量。 Only entity types, enumeration types or primitive types are supported in this context 在此上下文中仅支持实体类型,枚举类型或原始类型

I know the error is because in GetTraining Function, the includeEmployeeTrainingsQuery is null. 我知道错误是因为在GetTraining函数中,includeEmployeeTrainingsQuery为null。 But how do I do solve this problem ? 但是我该如何解决这个问题呢?

Your problem is, that the compiler cannot work out the type of null in your anonymous type variable training . 您的问题是,编译器无法在您的匿名类型变量training出null的类型。

One solution would be to create a strongly typed result using ViewModels. 一种解决方案是使用ViewModels创建强类型结果。 Those can be null using something like (Viewmodelclass)null . 可以使用(Viewmodelclass)null类的参数将(Viewmodelclass)null Or you can simply avoid assigning null using classic if statements, instead of ternary operators: 或者,您可以避免使用经典if语句而不是三元运算符来分配null:

public class QuestionsQueryVm {
    public foo bar {get; set; }
}
public class EmplyeeTrainingVm {
    public foo bar {get; set; }
}


public class TrainingVm {
    public QuestionsVm  Questions { get; set;}
    public EmployeeTrainingsVm EmployeeTraining { get; set; }
    public Training Training
}

So now you can start from the top: 现在,您可以从顶部开始:

var training = dbContext.tblTraining.Where(tc => tc.ID == ID)
var trainingVm = new TrainingVm {
    Training = training.FirstOrDefault(), // should be only one
}; 

if(includeQuestions) 
{
   var questions = training.Select(tc => new QuestionsQueryVm
   {
        Questions = tc.tblQuestions.Where(qq => qq.IsActive == true),
        Answers = tc.tblQuestions.Select(qq => qq.tblAnswers.Where(qa => qa.IsActive == true)),
   });
   trainingVm.Questions = questions;
}

if(includeEmployeeTrainings) 
{
    employeeTraining = training.Select(tc => newEmplyoeeTraingVm
    {
         EmployeeTrainings = tc.tblEmployeeTrainings.AsEnumerable()
    });
    trainingVm.EmployeeTraining = employeeTraining;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM