2012-06-20 100 views
1

我對NHibernate有點新鮮。我希望使用C#實現一個使用asp.net的Web應用程序。Nhibernate多對多多列,

我有以下的數據庫模式:

Database Schemas

這裏是我的NHibernate的映射文件。我不確定我的地圖是否正確。如果我犯了錯,請糾正我的錯誤。

<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"> 
    <class name="TelDir.Core.Domain.Status, TelDir.Core" table="tblStatus" lazy="false"> 
    <id name="ID" column="StatusID" unsaved-value="0"> 
     <generator class="identity" /> 
    </id> 

    <property name="StatusCode" column="StatusCode" /> 
    <property name="StatusName" column="StatusName" /> 

    <!-- 
    <set name="WorkOrderStatus" table="tblWorkOrderStatus" inverse="true"> 
     <key column="StatusID" /> 
     <one-to-many class="TelDir.Core.Domain.WorkOrderStatus, TelDir.Core" /> 
    </set> 
    --> 
    </class> 

</hibernate-mapping> 



<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"> 
    <class name="TelDir.Core.Domain.WorkOrder, TelDir.Core" table="tblWorkOrder" lazy="false"> 
    <id name="ID" column="WOID" unsaved-value="0"> 
     <generator class="identity" /> 
    </id> 
    <property name="WorkOrderRef" column="WORef" /> 
    <property name="WorkOrderDesc" column="WODesc" /> 


    <set name="WorkOrderStatus" table="tblWorkOrderStatus" inverse="true"> 
     <key column="WOID" /> 
     <one-to-many class="TelDir.Core.Domain.WorkOrderStatus, TelDir.Core" /> 
    </set> 

    </class> 
</hibernate-mapping> 



<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"> 
    <class name="TelDir.Core.Domain.WorkOrderStatus, TelDir.Core" table="tblWorkOrderStatus" lazy="false"> 
    <composite-id> 
     <key-many-to-one name="WorkOrder" column="WOID"/> 
     <key-many-to-one name="Status" column="StatusID"/> 
    </composite-id> 
    <property name="LastModifyDateTime" column="LastModifiedOn" type="Timestamp" /> 
    <property name="CreatedBy" column="CreatedBy" /> 
    </class> 
</hibernate-mapping> 

我的POCO類列示如下

public class Status : DomainObject<Int16> 
    { 
     private string _statuscode = ""; 
     private string _statusname = ""; 
     //private ISet<WorkOrderStatus> _workorder_status = new HashedSet<WorkOrderStatus>() ; 

     public Status() { } 

     public Status(string statusCode, string statusName) { 
      this._statuscode = statusCode; 
      this._statusname = statusName; 
     } 

     public string StatusCode  { 
      get { return _statuscode ; } 
      set { _statuscode = value; } 
     } 

     public string StatusName 
     { 
      get { return _statusname; } 
      set { _statusname = value; } 
     } 

     /* 
     public ISet<WorkOrderStatus> WorkOrderStatus 
     { 
      get { return (_workorder_status); } 
      protected set { _workorder_status = value; } 
     } 
     */ 
    } 



    public class WorkOrder : DomainObject<long> 
    { 
     private string _workorder_ref = ""; 
     private string _workorder_desc = ""; 
     private ISet<WorkOrderStatus> _workorder_status = new HashedSet<WorkOrderStatus>(); 

     public WorkOrder() { } 

     public WorkOrder(string wref, string wdecs) { 
      this._workorder_ref = wref; 
      this._workorder_desc = wdecs; 
     } 

     public string WorkOrderRef { 
      get { return _workorder_ref ; } 
      set { _workorder_ref = value; } 
     } 

     public string WorkOrderDesc 
     { 
      get { return _workorder_desc; } 
      set { _workorder_desc = value; } 
     } 


     public ISet<WorkOrderStatus> WorkOrderStatus 
     { 
      get { return (_workorder_status); } 
      protected set { _workorder_status = value; } 
     } 


     public void AddStatus(Status st, DateTime dt) 
     { 
       WorkOrderStatus obj = new WorkOrderStatus(); 
       obj.WorkOrder = this; 
       obj.Status = st; 
       obj.LastModifyDateTime = dt; 
       _workorder_status.Add(obj); 
     } 
    } 


    public class WorkOrderStatus 
    { 
     private DateTime _lastmodifydt; 
     private WorkOrder _workorder; 
     private Status _status; 
     private int _createdby; 

     public WorkOrderStatus() { 
     } 



     public DateTime LastModifyDateTime{ 
      get { return _lastmodifydt; } 
      set { _lastmodifydt = value; } 
     } 

     public WorkOrder WorkOrder 
     { 
      get { return _workorder; } 
      set { _workorder = value; } 
     } 
     public Status Status 
     { 
      get { return _status; } 
      set { _status = value; } 
     } 

     public int CreatedBy { 
      get { return _createdby; } 
      set { _createdby = value; } 
     } 


     public override bool Equals(object other) 
     { 

      //if (this == other) return true; 

      //WorkOrderStatus obj = other as WorkOrderStatus; 
      //if (obj == null) return false; // null or not a cat 

      //if (_lastmodifydt != obj._lastmodifydt) return false;    

      //return true; 


      if (other == null) 
       return false; 
      WorkOrderStatus t = other as WorkOrderStatus; 
      if (t == null) 
       return false; 
      if (WorkOrder == t.WorkOrder && Status == t.Status && _lastmodifydt == t.LastModifyDateTime) 
       return true; 
      return false; 
     } 

     public override int GetHashCode() 
     { 

      unchecked 
      { 
       int result; 
       result = _lastmodifydt.GetHashCode(); 
       result = 29 * result + WorkOrder.GetHashCode() + Status.GetHashCode(); 
       return result; 
      } 

      //return (WorkOrder.ID + "|" + Status.ID + "|" + Status.StatusName).GetHashCode(); 
     } 

    } 

我想我的數據存在於表所示:

[tblWorkOrderStatus]

StatusID   WOID    LastModifiedOn    CreatedBy 
-------------------------------------------------------------------------- 
2     1     06/20/2012 09:45:40.209   1 

[tblWorkOrder ]

WOID    WORef    WODesc 
------------------------------------------- 
    1    001    Test-001 

[tblStatus]

StatusID   StatusCode  StatusName 
----------------------------------------------- 
    1    'X001'   OPEN 
    2    'X002'   CLOSE 

我應該怎麼做添加記錄[tblWorkOrderStatus]?

我已經寫了如下測試代碼,但我發現沒有記錄添加在關聯表[tblWorkOrderStatus]中,我不知道它爲什麼不添加。

  WorkOrder Wo = new WorkOrder('001', 'Test-001'); 
      daoFactory.GetWorkOrderDao().Save(Wo); 

      Status St = daoFactory.GetStatusDao().GetById(1, false); 

       //// Secode Methode 
       WorkOrderStatus _objWS = new WorkOrderStatus(); 
       _objWS.WorkOrder  = Wo; 
       _objWS.Status  = St; 
       _objWS.LastModifyDateTime = DateTime.Now; 
       _objWS.CreatedBy = 1; //suppose 1 is current login UserID 

       Wo.WorkOrderStatus.Add(_objWS); 

      daoFactory.GetWorkOrderDao().Save(Wo); 

我可能會錯過POCO,NHibernate映射文件或其他地方的東西。你能否引導我找到正確的解決方案?

最好的問候,

這裏是我的堆棧跟蹤:

" at System.ThrowHelper.ThrowKeyNotFoundException()\r\n 
at System.Collections.Generic.Dictionary`2.get_Item(TKey key)\r\n 
at NHibernate.Engine.StatefulPersistenceContext.RemoveEntity(EntityKey key)\r\n 
at NHibernate.Action.EntityDeleteAction.Execute()\r\n 
at NHibernate.Engine.ActionQueue.Execute(IExecutable executable)\r\n 
at NHibernate.Engine.ActionQueue.ExecuteActions(IList list)\r\n 
at NHibernate.Engine.ActionQueue.ExecuteActions()\r\n 
at NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource session)\r\n 
at NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event)\r\n 
at NHibernate.Impl.SessionImpl.Flush()\r\n 
at NHibernate.Transaction.AdoTransaction.Commit()\r\n 
at TelDir.Data.NHibernateSessionManager.CommitTransaction() 
in E:\\OLD PC\\D\\WORKS\\PROJECT\\TelDIR\\Data\\NHibernateSessionManager.cs:line 120\r\n 
at TelDir.Web.NHibernateSessionModule.CommitAndCloseSession(Object sender, EventArgs e) 
in e:\\OLD PC\\D\\WORKS\\PROJECT\\TelDIR\\Web\\App_Code\\NHibernateSessionModule.cs:line 38\r\n 
at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()\r\n 
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)" 

回答

1

的主要問題是,有上WorkOrder.WorkOrderStatus沒有級聯,所以NHibernate的不知道要持續改變它發現集合中,當你保存。

我改變WorkOrder.hbm.xml所以set看起來是這樣的:

<set name="WorkOrderStatus" table="tblWorkOrderStatus" inverse="true" cascade="all-delete-orphan"> 
    <key column="StatusID" /> 
    <one-to-many class="TelDir.Core.Domain.WorkOrderStatus, TelDir.Core" /> 
</set> 

然後這個測試通過了:

// Arrange 
    var workorder = new WorkOrder("001", "Test-001"); 
    var status = new Status("1", "Status-1"); 

    workorder.AddStatus(status, DateTime.Now); 

    WorkOrderStatus expected; 

    // Act 
    using (ISession session = _factory.OpenSession()) 
    using (ITransaction tx = session.BeginTransaction()) 
    { 
     session.Save(status); 
     session.SaveOrUpdate(workorder); 

     tx.Commit(); 
    } 

    using (ISession session = _factory.OpenSession()) 
    using (ITransaction tx = session.BeginTransaction()) 
    { 
     expected = session.Query<WorkOrderStatus>() 
      .Fetch(s => s.Status) 
      .Fetch(s => s.WorkOrder) 
      .FirstOrDefault(); 
    } 

    // Assert 
    expected.Should().NotBeNull(); 
    expected.Status.Should().Be(status); 
    expected.WorkOrder.Should().Be(workorder); 

刪除

取消對ISet<WorkOrderStatus> WorkOrderStatus財產上Status。另外,在Status.hbm.xml中取消註釋<set name="WorkOrderStatus" ...,並像WorkOrder一樣添加屬性cascade="all-delete-orphan"

添加到工單:

public void RemoveStatus(WorkOrderStatus item) 
{ 
    if (!WorkOrderStatus.Contains(item)) return; 

    item.Status.WorkOrderStatus.Remove(item); 
    WorkOrderStatus.Remove(item); 
} 

現在,這個測試應該通過:

// Arrange 
    var workorder = new WorkOrder("001", "Test-001"); 
    var status = new Status("1", "Status-1"); 

    workorder.AddStatus(status, DateTime.Now); 

    WorkOrderStatus expected; 

    // Act 
    using (ISession session = _factory.OpenSession()) 
    using (ITransaction tx = session.BeginTransaction()) 
    { 
     session.Save(status); 
     session.SaveOrUpdate(workorder); 

     tx.Commit(); 
    } 

    using (ISession session = _factory.OpenSession()) 
    using (ITransaction tx = session.BeginTransaction()) 
    { 
     expected = session.Query<WorkOrderStatus>() 
      .Fetch(s => s.Status) 
      .Fetch(s => s.WorkOrder) 
      .FirstOrDefault(); 

     expected.WorkOrder.RemoveStatus(expected); 

     tx.Commit(); 
    } 

    using (ISession session = _factory.OpenSession()) 
    using (ITransaction tx = session.BeginTransaction()) 
    { 
     expected = session.Query<WorkOrderStatus>() 
      .Fetch(s => s.Status) 
      .Fetch(s => s.WorkOrder) 
      .FirstOrDefault(); 
    } 

    // Assert 
    expected.Should().BeNull(); 
+0

什麼是WorkOrder.hbm.xml點'<集名稱= 「WorkOrderStatus」 表中的不同= 「tblWorkOrderStatus」inverse =「true」cascade =「all-delete-orphan」> '和' '? – Veasna

+0

如何從關聯表[tblWorkOrderStatus]中刪除數據。 我想刪除當前添加的記錄。我怎麼辦? 我嘗試使用 WorkOrderStatus obj = new WorkOrderStatus(); obj.WorkOrder = this; obj.Status = st; obj.LastModifyDateTime = dt; obj.CreatedBy = UserID; _workorder_status.Remove(obj); 但沒有運氣可以刪除。 – Veasna

+0

我改變了'cascade =「all-delete-orphan」'。我編輯了我的答案,以反映移除項目。 – HackedByChinese