2009-08-26 66 views
0

我怎样才能让NHibernate的这种behaviuor:实现NHibernate的更新实体副本

有一个叫用户的实体在我的域名

// 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 - 就像版本。我试图使用版本映射属性,但它只是更新版本字段,重新创建完整的实体。什么方法会更好?

回答

1

我为我们的应用程序编写了一个版本控制系统。我将版本化的对象分成两个类,一个代表整个对象,另一个代表其版本。

在我们的软件中,版本控制是业务逻辑的一部分。应用程序提供对历史的访问,用户可以对版本控制进行一些控制。

因此在内存中创建新版本。您需要执行深层复制。您可以通过在根实体及其所有子项中实现接口来实现此目的。该接口提供了一种方法DeepCopy,该方法通过对象图递归调用。

object还有一个受保护的MemberwiseCopy方法,这可能会有所帮助。它不是一个深层次的副本。

我们不想让痛苦去维护复制每一个属性的代码。因此,我们使用序列在内存中拷贝的对象图:

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的实体的方法和做一些其他清理。这也是通过对象图递归地完成的。

现在,它工作正常。在未来,我们可能需要将其重构为接口实现,该实现稍微清晰一些。

0

根据历史是否不属于你的域逻辑,我建议使用触发器。通过不属于域逻辑的一部分,我的意思是 - 你不需要向用户展示它,你不会从历史版本中复制副本。

通过使用触发器,您有几个选择 - 最简单的(并且暗示您确实需要仅为少数表保存历史记录) - 将具有单独的_history表,它是您原始表的副本。

总而言之,这取决于你究竟是什么。