【翻訳】How-to:Using the N*Stack,part 5

14306 ワード

原文住所:Part 5: Fixing the Broken Stuff
これまでNHibernateと持続化に注目してきた.本編では,以前のモードとマッピングの問題を修正して,我々のテストに合格する.本編が終わったら、NHibernateへの関心を減らします.次の部分はNinjectの統合に集中し始め,我々の制御は注入のフレームワークを反転/依存し,ASPに加わる.NET MVCにて. 
他にも面白いことを言いますが、Fabio Mauloによると、NHibernateのLOGOは寝ているモルモット匹かもしれません.  
何を正すべきかを明らかにする
バグを修正するときは、バグのみを修正する必要があります.明らかに、私たちはテストを作成して、私たちはどこに問題があるかを見つけることができて、明らかではありませんのはどの“間違い”が実は間違いではありません.
自白:時々符号化してテストします.時々ズボンをはいてからシャツを着ます.実はあなたが家を出る前に服を着ていれば、順番はそんなに重要ではありません.同様に,符号化とテストの順序もそれほど重要ではない.
以下はpart 4のNUnitのテスト結果です.2つは合格し、3つは失敗し、5つは異常を投げ出しました.私にとって、10個のテストのうち2個が合格してとてもよかったです.残りの問題を一つ一つ解決しましょう.
最低限のNHibernateデバッグ
NHibernateはログフレームワークとしてlog 4 netを使用し、NUnitや他のテストツールのログを迅速かつ正確に表示します.
  • log 4 net.dllテスト項目への参照
  • appを追加する.configファイル
  • 新しいクラスBaseFixture
  • を追加
  • あなたのすべてのtest fixture継承BaseFixture
  • を設定します.
    次は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 。

    /Files/LeoXing/NStack/NStackExample.Part5.CSharp.zip