流畅的NHibernate多对多映射可以保存所有项目,但不能获得所有项目

时间:2014-09-10 22:32:23

标签: c# sql asp.net-mvc nhibernate fluent-nhibernate

我有一个课程表:

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

测验表:

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

问题表:

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

还有一个QuizQuestion表:

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

管理这些数据的前端看起来像这样(我希望我对它的外观有更多的发言权):

enter image description here

用户界面可能并不重要,但希望它能为您提供更好的主意。我使用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();
    }
}

是的,Quiz表由于某种原因映射到Exam类。发布表单时,我会查看每个复选框,确定QuizQuestion是否已存在,如果没有,则插入新行。这部分工作正常,但无论如何这里是代码:

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 );
}

比如说,我选择以下复选框:

enter image description here

发布表单后,我可以通过查看数据库中的QuizQuestion表来验证是否添加了新行:

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

但是,出于某种原因,新行不是下一页显示的数据集的一部分。在保存/提交/刷新/重定向之后,下一页看起来与以前完全一样:

enter image description here

视图不是问题,因为当我在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;
}

这里是Repository类的GetAll方法:

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

这件事最奇怪的部分是如果我重建解决方案,问题就会解决。它必须是重建,或者代码更改后跟构建。

这让我疯狂。我做错了什么?

修改

我怀疑这与NHibernate缓存有关,所以我应用了this mapping convention。然而,没有运气。

编辑2

正如我之前所说,重建会以某种方式刷新数据。我能够在ID为3的Quiz中添加几个问题,重建后它们出现在列表中。然后我删除了连接表中的所有行,但问题仍然是列表中的 。我现在更加确信这可能是NHibernate缓存的一个问题。

1 个答案:

答案 0 :(得分:0)

我终于找到了问题:

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

应该是:

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

似乎每次我遇到令人沮丧的NHibernate问题都是因为我错过了某个地方的ToList 调用。它开始让我紧张不安。