如何将 where 子句添加到 ThenInclude

Posted

技术标签:

【中文标题】如何将 where 子句添加到 ThenInclude【英文标题】:How to add where clause to ThenInclude 【发布时间】:2017-02-06 08:28:25 【问题描述】:

我有 3 个实体:

Questionnaire.cs:

public class Questionnaire

    public int Id  get; set; 
    public string Name  get; set; 
    public ICollection<Question> Questions  get; set; 

Question.cs:

public class Question

    public int Id  get; set; 
    public string Text  get; set; 
    public ICollection<Answer> Answers  get; set; 

Answer.cs

public class Answer

    public int Id  get; set; 
    public string UserId  get; set; 
    public string TextAnswer  get; set; 

所以我保存了带有答案的问卷,但现在我想检索带有问题及其答案的过滤问卷。所以我为此写了linq,但它给我一个错误,我做错了什么吗?这是一个例子:

questionnaire = _context.Questionnaires.Include(qn => qn.Questions)
.ThenInclude(question => question.Answers.Where(a => a.UserId == userId))
.FirstOrDefault(qn => qn.Id == questionnaireId);

我得到了

Message = "属性表达式 'q => 来自 q.Answers 中的答案 a 其中 Equals([a].UserId, __userId_0) select [a]' 无效。这 表达式应表示属性访问:'t => t.MyProperty'。

任何想法如何解决这个问题?

【问题讨论】:

你能告诉我你的查询是什么吗? 每个问卷都有问题,问题有答案,我需要通过userId过滤这些问题的答案。 我将您的模型类更改为在您的 answer 中有一个 Question 的导航属性。 var问卷= ctx.Answers.Include(q=>q.Question).Where(a =>a.UserId=="1").ToList(); 【参考方案1】:

不支持在IncludeThenInclude 中过滤。使用Select创建投影:

questionnaire = _context.Questionnaires
    .Select(n => new Questionnaire
    
        Id = n.Id,
        Name = n.Name,
        Questions = n.Questions.Select(q => new Question
        
           Id = q.Id,
           Text = q.Text,
           Answers = q.Where(a => a.UserId == userId).ToList()
        ).ToList()
    )
    .FirstOrDefault(qn => qn.Id == questionnaireId);

关于这个问题有个github issue:https://github.com/aspnet/EntityFramework/issues/3474

【讨论】:

【参考方案2】:

我认为您需要在答案中有问题的导航属性,因为答案应该有问题 Id 。你已经有了这个 FK,你只需要一个导航属性

您的模型类如下所示

public class Answer

    public int Id  get; set; 
    public string UserId  get; set; 
    public string TextAnswer  get; set; 
    // added in model
    public Question Question  get; set; 
 

像这样查询

  var answers = ctx.Answers.Include(q=>q.Question).Where(a =>a.UserId=="1").ToList();

【讨论】:

【参考方案3】:

您可以在内存中过滤导航属性:

var questionnaire= _context.Questionnaire.FirstOrDefault(qn => qn.Id == questionnaireId);

questionnaire.Answers = _context.Entry(questionnaire)
 .Collection(b => b.Answers )
 .Query()
 .Where(a => a.UserId == userId).ToList();

【讨论】:

以上是关于如何将 where 子句添加到 ThenInclude的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 4:将 where 子句添加到连接条件

如何将 WHERE 子句添加到 Power BI 中的 SQL 或 Access 数据源?

EF4 将 is null 子句添加到 where 子句

自动将分区条件添加到 WHERE 子句

如何使用 AREL 执行条件 where 子句

自动将一些 Where 子句添加到 Linq 表达式树