我想知道如何最好地实现一个属性(此处为LatestRequest
),该属性是只读的,由查询支持。
在这里,我有一个导出,可以请求多次发生。我想在Export上有一个属性来获取最新的ExportRequest
。目前,我已经使用公式进行多对一映射,如下所示:
<class name="Export" table="Exports">
<id name="Id">
<generator class="guid" />
</id>
<property name="Name" />
<bag name="Requests" cascade="all,delete-orphan" inverse="true" access="field.camelcase" order-by="CreationDate desc">
<key column="ExportId"/>
<one-to-many class="ExportRequest"/>
</bag>
<many-to-one name="LatestRequest"
class="ExportRequest"
formula="(select top 1 ExportRequests.Id from ExportRequests order by ExportRequests.CreationDate desc)"/>
</class>
<class name="ExportRequest" table="ExportRequests">
<id name="Id">
<generator class="native" />
</id>
<many-to-one name="Export"
class="Export"
column="ExportId"
not-null="true" />
<property name="CreationDate" />
<property name="Tag" />
</class>
但是,由于在获取导出时会获取ExportRequests.Id
LatestRequest
,因此此访问模式会返回过时数据:
var export = session.Get<Export>(exportId);
export.AddRequest(new ExportRequest(DateTime.Now, "Foo"));
Assert.AreEqual("Foo", export.LatestRequest.Tag); // fails due to stale data
session.Update(export);
那么,实现LatestRequest
属性的最佳方法是什么?
我可以更改LatestRequest
的getter,以便它执行Find
查询,该查询应该是最新的,但我不确定如何使导出知道会话。< / p>
答案 0 :(得分:1)
有几种方法可以解决这个问题。我可能不会尝试以这种方式“自动”。为了提高性能和简单性,我只是将它作为常规引用并在业务逻辑或实体中进行管理,如下所示:
class Export
{
private IList<ExportRequest> requests;
ExportRequest LatestRequest { get; private set; }
public void AddRequest (ExportRequest request)
{
requests.Add(request);
LatestRequest = request;
}
}
因此,您不需要任何特殊映射或任何其他查询来获取最新请求。而且,最重要的是,实体在内存中是一致的,并且不依赖于持久性。
无论如何解决它,实体和业务逻辑管理数据(在内存中)非常重要。应该是“坚持无知”。数据库和数据访问层不负责管理实体的关系和逻辑。