使用实体框架从多对多关系中选择数据

Posted

技术标签:

【中文标题】使用实体框架从多对多关系中选择数据【英文标题】:Selecting data from a many-to-many relation with Entity Framework 【发布时间】:2019-03-24 12:45:14 【问题描述】:

我有一个 Code First EF 设置,在两个类(测验和问题)之间存在多对多关系。它们看起来像这样:

public partial class Quiz

    public Quiz()
    
        Questionnaire = new HashSet<Question>();
    

    [Key]
    public int Id  get; set; 

    [Required]
    public string Naam  get; set; 

    public ICollection<Question> Questionnaire get; set; 


public partial class Question

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public Question()
    
        Quizzes = new HashSet<Quiz>();
        Answers = new HashSet<Answer>();
    

    [Key]
    public int Id  get; set; 

    [Column(TypeName = "ntext")]
    [Required]
    public string Content  get; set; 

    public int CategoryId  get; set; 

    public virtual ICollection<Quiz> Quizzes  get; set; 

    public virtual ICollection<Answer> Answers  get; set; 

    public virtual Category Category  get; set; 

我已在我的数据库中确认 EF 正确设置了链接表 QuizQuestions,并且种子数据似乎也正确填写了。

现在,问题来了。我有一个 ViewModel 类,它试图读取数据库中的所有测验并添加与每个测验相关的问题数量。问题是,“问卷”属性没有被填写,我不知道为什么。 ViewModel 使用如下代码:

using (var context = new KwisContext())
        
            var quizzes = context.Quizzes.ToList().Select(q => new QuizVM(q));
            Quizzes = new ObservableCollection<QuizVM>(quizzes);
        

QuizVM 看起来像这样:

public class QuizVM

    private Quiz _q;

    public QuizVM(Quiz q)
    
        _q = q;
    

    public string Naam
    
        get  return _q.Naam; 
    

    public int QuestionCount
    
        get 
            return _q.Questionnaire.Count;
        
    

我已经将我的代码与尝试做类似事情的人进行了比较(它适用于大学),但它适用于他的代码,而不适用于我的代码,我终生无法看到我们的方法有什么不同。有什么我可以在 Entity Framework 中搞砸的东西导致它失败吗?

编辑: 我忘了提到我已经尝试过相同的代码,但从另一端开始,即请求数据库中的每个问题并计算它们所属的测验数量。我用与上面相同的代码编写了这个,这确实有效。

【问题讨论】:

很可能是延迟加载。 ICollection 问卷未加载(在 context.Quizzes.ToList() 中,除非明确要求 我对 linq 相当缺乏经验,我该如何明确地请求它?另外,在我对 OP 的编辑中给出信息后,您仍然认为是这种情况吗? 【参考方案1】:

明确使用Include 获取关联数据

context.Quizzes.Include(x=>x.Questionnaire).ThenInclude(x=>x.OthersThatYouNeed)......

【讨论】:

这会引发错误,指出 Include 的参数必须是字符串,而不是 lambda 表达式。编辑:它实际上导致了问题的解决,我们只是这样编写代码:context.Quizzes.Include("Questionnaire") 等。感谢您的启发! 我想知道您使用的是哪些词:问题或问卷。因为您在 QuizVM 中使用“问题”,但在“课堂测验”中使用“问卷”,所以我只选择其中一个作为示例。避免使用Include("Questionnaire"),一旦你有TYPO字,很难找到问题,所以总是使用强类型语法:LambdaExpression 或nameof(property) 在示例中这实际上是我的错误,我之前尝试过调用属性“问题”而不是“问卷调查”来查看 EF 是否关心变量名。我改回来了,但忘记在 QuizVM 中编辑示例。

以上是关于使用实体框架从多对多关系中选择数据的主要内容,如果未能解决你的问题,请参考以下文章

如何从多对多表中选择一对一关系

Jooq 从多对多关系中选择 pojos

使用非关联数据 (LINQ) 从多对多关系中获取值

从多对多关系中获取数据

从多对多关系中获取核心数据

如何仅从多对多映射表加载 id?