【翻訳】How-to:Using the N*Stack,part 5
これまでNHibernateと持続化に注目してきた.本編では,以前のモードとマッピングの問題を修正して,我々のテストに合格する.本編が終わったら、NHibernateへの関心を減らします.次の部分はNinjectの統合に集中し始め,我々の制御は注入のフレームワークを反転/依存し,ASPに加わる.NET MVCにて.
他にも面白いことを言いますが、Fabio Mauloによると、NHibernateのLOGOは寝ているモルモット匹かもしれません.
何を正すべきかを明らかにする
バグを修正するときは、バグのみを修正する必要があります.明らかに、私たちはテストを作成して、私たちはどこに問題があるかを見つけることができて、明らかではありませんのはどの“間違い”が実は間違いではありません.
自白:時々符号化してテストします.時々ズボンをはいてからシャツを着ます.実はあなたが家を出る前に服を着ていれば、順番はそんなに重要ではありません.同様に,符号化とテストの順序もそれほど重要ではない.
以下はpart 4のNUnitのテスト結果です.2つは合格し、3つは失敗し、5つは異常を投げ出しました.私にとって、10個のテストのうち2個が合格してとてもよかったです.残りの問題を一つ一つ解決しましょう.
最低限のNHibernateデバッグ
NHibernateはログフレームワークとしてlog 4 netを使用し、NUnitや他のテストツールのログを迅速かつ正確に表示します.
次はappです.configファイルのlog 4 netの構成:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/>
</configSections>
<log4net>
<appender name="Debugger" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline"/>
</layout>
</appender>
<logger name="NHibernate.SQL">
<level value="ALL"/>
<appender-ref ref="Debugger"/>
</logger>
</log4net>
</configuration>
BaseFixture
public abstract class BaseFixture
{
protected static readonly log4net.ILog Log = GetLogger();
private static log4net.ILog GetLogger()
{
log4net.Config.XmlConfigurator.Configure();
return log4net.LogManager.GetLogger(typeof(BaseFixture));
}
}
log4net.Config.XmlConfiguration.Configure(), app.config , ConsoleAppender ,log4net Console.Out 。 , NHibernate SQL。
, Ayende NHProf.
#1
NStackExample.Data.Tests.CourseMappingTests.CanCascadeOrphanDeleteFromCourseToSections:
NHibernate.TransientObjectException : object references an unsaved transient instance -
save the transient instance before flushing. Type: NStackExample.Section, Entity: NStackExample.Section
Course Course = new Course {
Subject = "SUBJ",
CourseNumber = "1234",
Title = "Title",
Description = "Description",
Hours = 3 };
Section Section = new Section {
FacultyName = "FacultyName",
RoomNumber = "R1",
SectionNumber = "1",
Term = Term };
Course.AddSection(Section);
using (ITransaction Tran = Session.BeginTransaction())
{
ID = (Guid) Session.Save(Course);
Session.Save(Section);
Tran.Commit(); //<====
}
Session.Clear();
, session 。 。 , 。 , 。 , (INSERT) course , course section 。 TestCascadeSaveFromParentToChild , 。 , , , section 。
, 。 , 。
//Test removing
Course.RemoveSection(Section);
using (ITransaction Tran = Session.BeginTransaction())
{
Session.SaveOrUpdate(Course);
Tran.Commit();
}
Session.Clear();
, , Session.Save(Course) ,Session.Save 。 course, Session.SaveOrUpdate Session.Update。 , , , 。
, :
NStackExample.Data.Tests.CourseMappingTests.CanCascadeOrphanDeleteFromCourseToSections:
NHibernate.Exceptions.GenericADOException :
could not delete collection: [NStackExample.Course.Sections#912b489a-4d12-4bc9-9d68-9c6b0147b799]
[SQL: UPDATE "Section" SET Course_id = null WHERE Course_id = @p0]
----> System.Data.SQLite.SQLiteException : Abort due to constraint violation
Section.Course_id may not be NULL
section course ,NHibernate Section Course_id NULL。 。 , section 。 。 course , section Cascade.AllDeleteOrphan()。
HasMany(x => x.Sections)
.AsSet()
.ForeignKeyConstraintName("CourseSections")
.Cascade.AllDeleteOrphan()
, :
NStackExample.Data.Tests.CourseMappingTests.CanCascadeOrphanDeleteFromCourseToSections:
NHibernate.PropertyValueException :
not-null property references a null or transient valueNStackExample.Section.Course
。 , section ,NHibernate Section.Course = null / nothing。 , NHibernate , Section.Course 。 log4net NHibernate.SQL , NOT NULL , , NHibernate 。
。 one-to-many ,many-to-one , , , 。 。 BUG, NHibernate “ ” , 。 one-to-many。 course’s sections 。 many-to-one : Section Course 。 , Course.Sections Inverse() 。 NHibernate “ ”。
Bug , ! , , 。
#2
NStackExample.Data.Tests.CourseMappingTests.CanCascadeSaveFromCourseToSections:
Expected: <nstackexample.section>
But was: <nstackexample.section>
。 section 。
Q: section ?
A: ,Object.Equals 。 , 。 。
Q: ?
A: section, 。 , sections? 。
Q: ?
A: base Entity Equals, 。
Q: ?
A: ID 。
Q: ID ?
A: 。 , Equals 。
:
public override bool Equals(object obj)
{
Entity other = obj as Entity;
if (other == null)
return false;
return ID.Equals(other.ID) && !ID.Equals(Guid.Empty);
}
, !10 6 。
#3
NStackExample.Data.Tests.SectionMappingTests.CanCascadeSaveFromSectionToStudentSections:
NHibernate.PropertyValueException :
not-null property references a null or transient valueNStackExample.Student.MiddleName
。 Student MiddleName 。 Section , MiddleName 。 , MiddleName , 。 。 NULL NullReferenceExceptions 。 MiddleName = string.Empty。 , 。
NStackExample.Data.Tests.SectionMappingTests.CanCascadeSaveFromSectionToStudentSections:
NHibernate.TransientObjectException :
object references an unsaved transient instance - save the transient instance before flushing.
Type: NStackExample.StudentSection, Entity: NStackExample.StudentSection
。 ? StudentSection one-to-many 。 Sections Students StudentSection, Cascade.All Inverse()。
。 。
#4
NStackExample.Data.Tests.StudentMappingTests.CanCascadeSaveFromStudentToStudentSection:
NHibernate.TransientObjectException : object references an unsaved transient instance -
save the transient instance before flushing. Type: NStackExample.Student, Entity: NStackExample.Student
BUG。 , Student, Section。 。 #3 MiddleName BUG, , 。 NullReferenceException 。 ?
Student , 。 - 。 :
//Check the results
using (ITransaction Tran = Session.BeginTransaction())
{
Student = Session.Get<Student>(ID);
Assert.AreEqual(1, Student.StudentSections.Count);
Assert.AreEqual(StudentSection, Student.StudentSections.First());
Tran.Commit();
}
!
#5
NStackExample.Data.Tests.TermMappingTests.CanCascadeSaveFromTermToSections:
NHibernate.TransientObjectException : object references an unsaved transient instance -
save the transient instance before flushing. Type: NStackExample.Section, Entity: NStackExample.Section
#3 。 term section。 Term.Sections Cascade,All() Inverse()。
#6
NStackExample.Data.Tests.TermMappingTests.CanSaveAndLoadTerm:
Expected: "Fall 2009"
But was: null
, Term Name , null / nothing。 , 。 , Name , 。 , 。 ,EndDate December 1st, 2009 。