我有一个课程表:
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
管理这些数据的前端看起来像这样(我希望我对它的外观有更多的发言权):
用户界面可能并不重要,但希望它能为您提供更好的主意。我使用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 );
}
比如说,我选择以下复选框:
发布表单后,我可以通过查看数据库中的QuizQuestion表来验证是否添加了新行:
QuizID QuestionID
--------------------
1 1
1 2
2 2
2 3
3 1
3 3
但是,出于某种原因,新行不是下一页显示的数据集的一部分。在保存/提交/刷新/重定向之后,下一页看起来与以前完全一样:
视图不是问题,因为当我在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。然而,没有运气。
正如我之前所说,重建会以某种方式刷新数据。我能够在ID为3的Quiz中添加几个问题,重建后它们出现在列表中。然后我删除了连接表中的所有行,但问题仍然是列表中的 。我现在更加确信这可能是NHibernate缓存的一个问题。
答案 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 调用。它开始让我紧张不安。