我有一个User对象,上面有一个Country对象。我在用户映射文件中用多对一标签映射它:
<many-to-one name="Country" column="CountryID" cascade="none"/>
如何更新用户所在的国家/地区?
目前,我的用户界面有一个国家/地区下拉列表,新国家/地区的ID会传递给控制器。然后,控制器根据该值设置用户所在国家/地区的ID。所以:
var user = session.Get<User>(userID);
user.Country.ID = Convert.ToInt32(Request.Form["Country_ID"]);
但是当我打电话时:
session.SaveOrUpdate(user);
我收到一条错误消息,说“国家/地区实例的标识符已从7更改为8”。大概这是因为NHibernate将Country对象标记为脏了?我不想更新国家/地区对象,只是用户中的ID引用。有可能这样做吗?
谢谢, 乔恩
答案 0 :(得分:1)
您始终可以获取基础连接并手动执行更新。
答案 1 :(得分:0)
var user = session.Get<User>(userID);
user.Country = session.Get<Country>(Convert.ToInt32(Request.Form["Country_ID"]));
您必须从数据库中检索国家/地区,然后将其设置为用户
答案 2 :(得分:0)
感谢安德斯。当我们所做的只是更新对该对象的引用时,为什么我们需要首先获取对象的额外开销?
实际上,我们的控制器会自动反序列化对象的请求。难道我们无法告诉NHibernate忽略国家/地区对象的更新而只是更新用户?我原以为cascade =“none”会这样做。
如果对象上有多个需要更新的多对一对象,会发生什么?在保存之前将它们全部收回,这是一个很大的开销。
答案 3 :(得分:0)
这真的会否定首先使用ORM的整个目的,不是吗?更新像这样的子对象的正常模式是什么?当然这是一种非常常见的情况。是加载每一个:
var user = session.Get<User>(userID);
user.Country = session.Get<Country>(Convert.ToInt32(Request.Form["Country_ID"]));
user.Manager = session.Get<User>(Convert.ToInt32(Request.Form["Manager_ID"]));
user.State = session.Get<State>(Convert.ToInt32(Request.Form["State _ID"]));
user.Region = session.Get<Region>(Convert.ToInt32(Request.Form["State _ID"]));
我们是否真的需要为每个子对象进行额外的数据库调用(事件虽然这些对象没有被更新)?
目前我们有:
var ds = new NameValueDeserializer();
var entity = session.Get<TEntity>(entityID);
ds.Deserialize(entity, form);
session.Update(entity);
因此,这通常适用于所有实体。必须专门加载子对象以保存实体将是不必要的编码开销(以及进行额外的数据库调用)。
在配置,映射,拦截器等方面是否没有办法解决这个问题?有谁知道为什么Hibernate采取了这个设计决定?
答案 4 :(得分:0)
你应该把这个讨论带到NHibernate用户组。