我对NHibernate有点新鲜。我希望使用C#使用asp.net实现一个Web应用程序。
我有以下数据库模式:
这是我的NHibernate Mapping文件。我不确定我的映射是否正确。如果我做错了,请纠正我。
<?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映射文件或其他地方遗漏一些东西。你能指导我找到合适的解决方案吗?
致以最诚挚的问候,
这是我的stacktrace:
" 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)"
答案 0 :(得分: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" ...
,并像在cascade="all-delete-orphan"
上一样添加属性WorkOrder
。
添加到WorkOrder:
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();