【发布时间】:2017-12-13 11:02:11
【问题描述】:
我正在开发一个更大的应用程序,它试图遵循分层架构模式。在 DBAL 上,我使用流畅配置的 NHibernate。数据库对象有时具有如下关联:
public class HeaderDbo
{
public HeaderDbo()
{
Details = new List<DetailDbo>();
}
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual IList<DetailDbo> Details { get; set; }
}
public class DetailDbo
{
public virtual int Id { get; set; }
public virtual string DetailName { get; set; }
public virtual HeaderDbo Header { get; set; }
public virtual RelevantObjectDbo RelevantObject { get; set; }
}
public class RelevantObjectDbo
{
public virtual int Id { get; set; }
public virtual string RelevantText { get; set; }
}
映射如下:
public class HeaderDboMap : ClassMap<HeaderDbo>
{
public HeaderDboMap()
{
Table("Header");
Id(x => x.Id).Column("Id");
Map(x => x.Name);
HasMany(x => x.Details)
.Inverse()
.Cascade.All();
}
}
public class DetailDboMap : ClassMap<DetailDbo>
{
public DetailDboMap()
{
Id(x => x.Id).Column("Id");
Table("Detail");
Map(x => x.DetailName);
References(x => x.Header).Column("HeaderId");
References(x => x.RelevantObject).Column("RelevantObjectId")
.Cascade.SaveUpdate(); //??
}
}
public class RelevantObjectDboMap : ClassMap<RelevantObjectDbo>
{
public RelevantObjectDboMap()
{
Id(x => x.Id).Column("Id");
Table("RelevantObject");
Map(x => x.RelevantText);
}
}
现在,DBO 映射到的应用程序域实体不一定一对一地反映数据库结构。例如,Header 可能保留为 header,但 Detail 会,例如,由 DetailDbo 和 RelevantObjectDbo 的部分组成。然后应用程序对实体执行它的操作 - 发生 Detail 的一些转换,现在需要持久化。
假设我只影响了 Detail 实体中需要进入 Detail 表的部分,而不会以任何方式影响 RelevantObject 表。考虑模型的方式可能是错误的,但我们还需要对持久化的工作原理进行实际操作。所以,比如说,我只想让 NHibernate 更新 Detail 表而不“接触” RelevantObject 表上的任何内容。实际上,这正是问题所在:我该如何实现?
当然,在现实中,DB 模型更大更复杂,应用程序逻辑也是如此。可能有一部分 BL 根本不处理数据的 RelevantObject 部分,因此即使 DBO 完全从数据库加载,并非所有数据都能进入应用程序模型。但是要将数据持久化回数据库 - 似乎我需要完全水合数据库模型,但这并不总是实用的。那么,我们如何指示 NHibernate “不接触” RelevantObject - 换句话说,不更新 dbo.Detail.RelevantObjectId?
我尝试将不同的 Cascade 选项应用于 DetailDbo.RelevantObject 属性,但如果它保持为空,NHibernate 总是希望将 RelevantObjectId 设置为 NULL - 我想,这是正确的。
我不明白如何在不必通过所有关联加载和保存数据库的一半的情况下对与我的 BL 的“部分”相关的数据进行更改。
谢谢!
【问题讨论】:
-
我发现如果我在 DetailDbo.RelevantObject 上将 Cascade 设置为 None 并将属性设置为一个“空”对象并设置了正确的 ID,那么更新会按照我想要的方式进行,即参考 dbo.Detail.RelevantObjectId 保持正确设置并且 dbo.RelevantObject 没有被触及。但是,我认为这太笨拙了 - 没有更好的方法吗?
-
我现在正在研究的一个策略是:在负责从 db 加载实体和保存的存储库中,我们首先读取 DBO - 在存储库“想要”的范围内,更新它实体中的对象并将其保存回来。这也有点笨拙,但我喜欢这种方法,因为“持久化什么”的逻辑包含在 DBAL 中,这似乎很合适,因为实体应该与持久性细节无关。现在正在尝试以某种经济的方式实现这一点......
标签: c# nhibernate architecture fluent-nhibernate multi-layer