如何在NHibernate中制作这样的行为:
我的域名中有一个名为User的实体
// I ommit mapping attributes
public class User
{
int Id {get; set;}
int pId {get; set;}
//....other props, such as Login, Name, email...
}
我需要在更新时制作完整的副本。必须将pId设置为原始ID。旧实体必须不受影响。
所以这必须像某个版本控制系统,其中pId - 是不可变的标识,Id - 就像版本一样。我试图使用版本映射属性,但它只是更新版本字段,而不是重新创建完整的实体。什么方法会更好?
答案 0 :(得分:1)
我为我们的应用程序编写了一个版本控制系统。我将版本化对象拆分为两个类,一个代表整个对象,另一个代表其版本。
在我们的软件中,版本控制是业务逻辑的一部分。该应用程序提供对历史记录的访问,用户可以控制版本控制。
因此在内存中创建了新版本。您需要执行深层复制。您可以通过在根实体及其所有子节点中实现接口来实现此目的。该接口提供了一个方法DeepCopy
,它通过对象图递归调用。
MemberwiseCopy
中还有一个受保护的object
方法,可能会有所帮助。它不是一个很深的副本。
我们不希望痛苦地维护复制每个属性的代码。所以我们使用序列化来复制内存中的对象图:
public static T CopyDataContract<T>(T obj)
{
NetDataContractSerializer serializer = new NetDataContractSerializer();
using (MemoryStream stream = new MemoryStream())
{
serializer.Serialize(stream, obj);
stream.Position = 0;
return (T)serializer.Deserialize(stream);
}
}
此外,我们在实体中有重置id并进行其他清理的方法。这也是通过对象图递归完成的。
目前,它运作正常。将来我们可能需要将它重构为接口实现,这有点清晰。
答案 1 :(得分:0)
根据历史记录是否不属于您的域逻辑,我建议使用触发器。通过不属于域逻辑,我的意思是 - 您不需要向用户显示它,也不会使用历史版本制作副本。
通过使用触发器,您有几个选项 - 最简单的(并且暗示您确实只需要为少数几个表保存历史记录) - 将有一个单独的_history表,它是原始表的副本。
总而言之,这取决于你究竟追求的是什么。