我正在玩NHibernate 3.0。到目前为止,事情非常酷。我正在尝试附加之前没有分离的实体:
var post = new Post(){ Id = 2 };
session.Update(post); // Thought this would work but it doesn't.
post.Title = "New Title After Update";
session.Flush();
我尝试编写的内容如下:
var post = new Post(){ Id = 2 };
session.Attach(post);
post.Title = "New Title After Update";
session.Flush(); // Sql should be something like: UPDATE Post SET Title='New Title After Update' WHERE Id=2
这是否可行,只有Title
才会更新?这在EntityFramework中目前是可行的。当我只需要更新一些属性时,我不想从数据库加载Post
。另外,我正在尝试避免一个创建对象的方法调用...因为我认为它正在逐渐远离面向对象的方法。
编辑:我知道使用交易,我只是使用Flush()
来简化代码。好的,我认为我们正在努力实现我想要实现的目标。我希望能够使用构造函数创建一个具有已知Id的实体,就像我在上面的第二个代码块中一样。我不想打电话给Get<T>
或Load<T>
,因为在数据库中已经存在这样的对象构建这样的对象感觉相当错误。例如,在实体框架中,我可以编写第二个代码示例,它将“正常工作”。它只更新Title
属性。
答案 0 :(得分:4)
您可以session.Save()
或session.SaveOrUpdate()
好的,我想我现在知道你要做什么了。您正在尝试更新以前保留的Post
上的单个属性,而不是新的Post
,为此,您要实例化新的Post
并为其Id
提供var post = session.Load<Post>(2);
post.Title = "New Title";
session.SaveOrUpdate(post);
1}}数据库中的一个。
当你说你试图避免一个会创建对象的方法调用时,我不确定你是什么意思,但用NHibernate做这个的方法是:
Flush()
一般情况下,您不应在会话中致电session.Load
。
这里要注意的重要事项是使用Load
。使用id 调用Post
不会从数据库加载实体。只有当/您访问它们时,才会加载实体的属性值。
当然,在这种情况下,我相信NHibernate 将加载Title
的属性,(除非你指定了一个急切的获取模式,否则不会收集集合),并且有意义(坦率地说,我不明白为什么EF不会加载实体)。如果您的{{1}}属性的setter做了重要事情,比如检查现有标题,验证标题长度,检查您的凭据或更新其他属性,该怎么办?仅仅向数据库发送UPDATE是不够的。
答案 1 :(得分:1)
可以通过在映射中设置dynamic-update来更新已更改的属性。但是,据我所知,如果不在某个时刻从数据库中检索对象,就不可能(没有恢复到SQL)来执行更新。
答案 2 :(得分:0)
使用Merge方法。你必须创建一个新的实例变量来接受附加的实体= nhibernate不会对你的分离实例做任何其他事情。
var post = new Post(){ Id = 2 };
post.Title = "New Title After Update";
// Must create a new instance to hold final attached entity
var attachedPost = session.Merge(post);
session.Update(attachedPost);
session.Flush();
// Use attachedPost after this if still needed as in session entity
这涵盖了您正在寻找的“附加”功能,但我不知道您将如何仅更新一个属性。如果尚未从数据库填充对象实例,则属性将不同。动态映射不会解决这个问题 - NHibernate将属性视为“更新”到一堆空值,空字符串。
要说,您正在创建一个新实例,但您实际在做的是更新现有实例。您正在直接使用ID而不是对象。你正在设置一个属性,现在有一个实例可能会闲置并做更多的事情,但它没有强制执行任何不变量,实际上可能与id属性之外的真实交易没有任何相似之处......
对我个人而言,这一切都让我感觉很反对。