Web services 如何使用NHibernate更新新创建的分离实体? 说明:

Web services 如何使用NHibernate更新新创建的分离实体? 说明:,web-services,nhibernate,serialization,session-state,entity-relationship,Web Services,Nhibernate,Serialization,Session State,Entity Relationship,假设我有一个对象图,它嵌套了好几层,每个实体之间都有双向关系 A -> B -> C -> D -> E 或者换句话说,A有一个B的集合,B有一个对A的引用,B有一个C的集合,C有一个对B的引用,等等 现在让我们假设我想要编辑C实例的一些数据。在Winforms中,我会使用如下内容: var instanceOfC; using (var session = SessionFactory.OpenSession()) { // get the instance

假设我有一个对象图,它嵌套了好几层,每个实体之间都有双向关系

A -> B -> C -> D -> E
或者换句话说,
A
有一个
B
的集合,
B
有一个对
A
的引用,
B
有一个
C
的集合,
C
有一个对
B
的引用,等等

现在让我们假设我想要编辑
C
实例的一些数据。在Winforms中,我会使用如下内容:

var instanceOfC;

using (var session = SessionFactory.OpenSession())
{
    // get the instance of C with Id = 3
    instanceOfC = session.Linq<C>().Where(x => x.Id == 3);
}

SendToUIAndLetUserUpdateData(instanceOfC);

using (var session = SessionFactory.OpenSession())
{
    // re-attach the detached entity and update it
    session.Update(instanceOfC);
}
var-instanceOfC;
使用(var session=SessionFactory.OpenSession())
{
//获取Id为3的C实例
instanceOfC=session.Linq(),其中(x=>x.Id==3);
}
SendToUIAndLetUserUpdateData(instanceOfC);
使用(var session=SessionFactory.OpenSession())
{
//重新附着分离的实体并更新它
会话更新(instanceOfC);
}
简单地说,我们从数据库中抓取一个持久实例,分离它,将其交给UI层进行编辑,然后重新附加它并将其保存回数据库

问题: 这对于Winform应用程序很好,因为我们始终使用相同的实体,唯一的区别是它从持久到分离再到持久

问题是,现在我正在使用web服务和浏览器,通过JSON数据发送数据。该实体被序列化为字符串,然后反序列化为新的实体。它不再是一个分离的实体,而是一个临时实体,恰好与持久实体(和更新的字段)具有相同的ID。如果我使用这个实体进行更新,它将消除与
B
D
的关系,因为它们不存在于这个新的临时实体中

问题:
我的问题是,如何通过web将分离的实体序列化到客户机,接收它们并保存它们,同时保留我没有明确更改的任何关系?我知道
ISession.SaveOrUpdateCopy
ISession.Merge()
(它们似乎做了相同的事情?),但如果我不显式地设置它们,这仍然会消除关系。我可以将临时实体中的字段一个一个地复制到持久实体中,但在关系方面,这样做效果不太好,我必须手动处理版本比较。

我使用一个中间类来保存来自web服务的数据,从而解决了这个问题,然后将其属性复制到数据库实体。例如,假设我有两个这样的实体:

实体类
Album
包含
Photo
对象的集合,
Photo
引用了它所在的
Album
,因此它是一种双向关系。然后,我创建了一个
phototo
类:

DTO类 现在假设我在数据库中存储了以下
Photo

服务器数据 然后,服务器将JSON反序列化为
phototo
对象。在服务器端,我们更新
照片
,如下所示:

var instanceOfC;

using (var session = SessionFactory.OpenSession())
{
    // get the instance of C with Id = 3
    instanceOfC = session.Linq<C>().Where(x => x.Id == 3);
}

SendToUIAndLetUserUpdateData(instanceOfC);

using (var session = SessionFactory.OpenSession())
{
    // re-attach the detached entity and update it
    session.Update(instanceOfC);
}
服务器代码
var photoDTO=DeserializeJson();
var photoDB=Session.Load(photoDTO.Id);//或者在URL中使用ID
//将属性从PhotoTo复制到photoDB
photoDB.Name=photoDTO.Name;

photoDB.Album=Session.Load自动将属性从DTO复制到实体,尤其是当实体有很多属性时。它省去了手工编写每个属性的麻烦,并且具有很多可配置性。

我还想补充一点,我还无法在网上找到任何涉及此问题的资源。我在分离实体上找到的所有NHibernate指南都将其作为一个应用程序范围内的参考,或者将其作为一个与任何其他实体没有关系的单一实体来处理。嗨,你有没有得到这个问题的答案?嗨,CraftyFella,我刚刚发布了一个答案,详细说明了我在我的案例中所做的事情。merge和saveorupdatecopy做了同样的事情,但saveorupdatecopy不再使用,merge是api标准的发展方向。根据我的经验,
merge()
在消除关系方面也有同样的问题。
public class PhotoDTO
{
    public virtual int Id { get; set; }
    public virtual int AlbumId { get; set; }
    public virtual string Name { get; set; }
    // note that the DTO does not have a PathToFile property
}
new Photo
{
    Id = 15,
    Name = "Fluffy Kittens",
    Album = Session.Load<Album>(3)
};
{
    "id": 15,
    "albumid": 3,
    "name": "Angry Kittens"
}
var photoDTO = DeserializeJson();
var photoDB = Session.Load(photoDTO.Id); // or use the ID in the URL

// copy the properties from photoDTO to photoDB
photoDB.Name = photoDTO.Name;
photoDB.Album = Session.Load<Album>(photoDTO.AlbumId);

Session.Flush(); // save the changes to the DB