简体   繁体   English

流利的NHibernate多对多映射可保存所有项目,但不会获取所有项目

[英]Fluent NHibernate many-to-many mapping saves all items but doesn't get all items

I have a Course table: 我有一个课程表:

CourseID    Name
--------------------
1           Course 1
2           Course 2
3           Course 3

A Quiz table: 测验表:

QuizID    CourseID    Name
----------------------------
1         1           Quiz 1
2         1           Quiz 2
3         1           Quiz 3

A Question table: 问题表:

QuestionID    Text
-----------------------------
1             What is foo?
2             What is bar?
3             What is foobar?

And a QuizQuestion table: 还有一个QuizQuestion表:

QuizID    QuestionID
--------------------
1         1
1         2
2         2
2         3

The front-end for managing this data looks like this (I wish I had more say in how it has to look): 用于管理这些数据的前端如下所示(我希望我对它的外观有更多的发言权):

在此处输入图片说明

The UI probably doesn't matter, but hopefully it gives you a better idea. 用户界面可能并不重要,但希望它能给您一个更好的主意。 I'm using Fluent NHibernate with the following mappings: 我正在使用Fluent NHibernate和以下映射:

public class CourseMapOverride : IAutoMappingOverride<Course>
{
    public void Override( AutoMapping<Course> mapping )
    {
        mapping.Table( "Course" );

        mapping.Id( x => x.Id ).Column( "CourseID" );

        mapping.HasMany( x => x.Exams )
               .KeyColumn( "CourseID" )
               .Cascade.All()
               .Inverse();
    }
}

public class ExamMapOverride : IAutoMappingOverride<Exam>
{
    public void Override( AutoMapping<Exam> mapping )
    {
        mapping.Table( "Quiz" );

        mapping.Id( x => x.Id ).Column( "QuizID" );

        mapping.References( x => x.Course ).Column( "CourseID" );

        mapping.HasManyToMany( x => x.Questions )
               .Table( "QuizQuestion" )
               .ParentKeyColumn( "QuizID" )
               .ChildKeyColumn( "QuestionID" )
               .Cascade.All();
    }
}

public class QuestionMapOverride : IAutoMappingOverride<Question>
{
    public void Override( AutoMapping<Question> mapping )
    {
        mapping.Table( "Question" );

        mapping.Id( x => x.Id ).Column( "QuestionID" );

        mapping.HasManyToMany( x => x.Exams )
               .Table( "QuizQuestion" )
               .ParentKeyColumn( "QuestionID" )
               .ChildKeyColumn( "QuizID" )
               .Cascade.All()
               .Inverse();
    }
}

Yes, the Quiz table maps to the Exam class for some reason. 是的,由于某种原因,测验表映射到Exam类。 When the form is posted, I look at each checkbox, determine whether the QuizQuestion already exists, and insert a new row if it doesn't. 发布表单后,我查看每个复选框,确定QuizQuestion是否已存在,如果不存在,则插入新行。 This part is working correctly, but here is the code anyways: 这部分工作正常,但是无论如何这是代码:

public void UpdateCourse( EditCourseModel model )
{
    var course = CourseRepository.Get( model.CourseID );

    course.Name = model.Name;

    foreach ( var examQuestionModel in model.Questions
                                            .SelectMany( q => q.ExamQuestions )
                                            .Where( eq => eq.Selected ) )
    {
        UpdateExamQuestion( course, examQuestionModel );
    }
}

private void UpdateExamQuestion( Course course, ExamQuestionModel model )
{
    var exam = course.Exams.First( e => e.Id == model.ExamID );

    if ( exam.Questions.Any( q => q.Id == model.QuestionID ) )
    {
        // it already exists
        return;
    }

    var question = QuestionRepository.Get( model.QuestionID );

    exam.Questions.Add( question );

    question.Exams.Add( exam );
}

Say, for instance, I select the following checkboxes: 举例来说,我选择了以下复选框:

在此处输入图片说明

After I post the form, I can verify the new row was added by looking at the QuizQuestion table in the database: 发布表单后,可以通过查看数据库中的QuizQuestion表来验证是否添加了新行:

QuizID    QuestionID
--------------------
1         1
1         2
2         2
2         3
3         1
3         3

For some reason, however, the new row is not part of the data set that is displayed on the following page. 但是,由于某种原因,新行不属于下一页显示的数据集。 After a save/commit/flush/redirect, the next page looks exactly like it did before: 保存/提交/刷新/重定向后,下一页看起来与之前完全一样:

在此处输入图片说明

It's not a problem with the view, because when I pause the debugger inside of the foreach loop in the GetQuestionModel method (below), exam.Questions is empty: 视图不是问题,因为当我在下面的GetQuestionModel方法中的foreach循环中暂停调试器时, exam.Questions为空:

public CourseModel GetCourseModel( int courseID )
{
    var course = CourseRepository.Get( courseID );

    var questions = QuestionRepository.GetAll()
                                      .Select( q => GetQuestionModel( course.Exams, q ) )
                                      .ToList();

    return new CourseModel
               {
                   CourseID = course.ID,
                   Name = course.Name,
                   Questions = questions,
               };
}

public QuestionModel GetQuestionModel( IEnumerable<Exam> exams, Question question )
{
    var model = new QuestionModel
                    {
                        QuestionID = question.ID,
                        Text = question.Text,
                        ExamQuestions = new List<ExamQuestionModel>(),
                    };

    foreach ( var exam in exams )
    {
        // exam.Questions is empty when exam.ID is 3
        var examQuestionIDs = exam.Questions.Select( q => q.ID );

        model.ExamQuestions.Add( new ExamQuestionModel
                                     {
                                         ExamID = exam.ID,
                                         QuestionID = question.ID,
                                         Selected = examQuestionIDs.Contains( question.ID ),
                                     } );
    }

    return model;
}

Here's the GetAll method from the Repository class: 这是Repository类中的GetAll方法:

public virtual IQueryable<T> GetAll()
{
    return LinqExtensionMethods.Query<T>( this.Session );
}

The strangest part of this whole thing is if I rebuild the solution the problem fixes itself. 整个过程中最奇怪的部分是,如果我重新构建解决方案,问题将自行解决。 It has to be a rebuild though, or a code change followed by a build. 但是它必须是重新构建,或者是代码更改,然后是构建。

This is driving me bonkers. 这使我疯狂。 What am I doing wrong? 我究竟做错了什么?

EDIT 编辑

I suspected this had something to do with NHibernate caching, so I applied this mapping convention . 我怀疑这与NHibernate缓存有关,因此我应用了此映射约定 No luck however. 但是没有运气。

EDIT 2 编辑2

As I said earlier, a rebuild somehow refreshes the data. 如前所述,重建可以以某种方式刷新数据。 I was able to add several questions to Quiz with ID of 3, and after rebuilding they appeared in the list. 我能够向ID为3的测验中添加几个问题,并在重建后将其显示在列表中。 Then I deleted all the rows in the join table, but the questions are still in the list. 然后,我删除了联接表中的所有行,但问题仍在列表中。 I'm even more convinced now that this might be a problem with NHibernate caching. 现在,我更加确信这可能是NHibernate缓存的问题。

I finally found the problem: 我终于找到了问题:

var questions = QuestionRepository.GetAll()
                                  .Select( q => GetQuestionModel( course.Exams, q ) )
                                  .ToList();

Should be: 应该:

var questions = QuestionRepository.GetAll()
                                  .ToList()
                                  .Select( q => GetQuestionModel( course.Exams, q ) )
                                  .ToList();

It seems like every time I have a frustratingly difficult problem with NHibernate it's because I'm missing a call to ToList somewhere. 似乎每次我在NHibernate中遇到一个令人沮丧的难题时,都是因为我在某个地方缺少对ToList的调用 It's starting to really get on my nerves. 它开始真的让我感到不安。

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

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