【发布时间】:2014-09-10 22:32:23
【问题描述】:
我有一个课程表:
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
管理这些数据的前端看起来像这样(我希望我对它的外观有更多的发言权):
UI 可能无关紧要,但希望它能给你一个更好的主意。我正在使用具有以下映射的 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();
}
}
是的,测验表出于某种原因映射到考试类。发布表单后,我查看每个复选框,确定 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。但是运气不好。
编辑 2
正如我之前所说,重建会以某种方式刷新数据。我能够在 ID 为 3 的测验中添加几个问题,重建后它们出现在列表中。然后我删除了连接表中的所有行,但问题在列表中仍然。我现在更加确信这可能是 NHibernate 缓存的问题。
【问题讨论】:
标签: c# sql asp.net-mvc nhibernate fluent-nhibernate