我想只使用NHibernate QueryOver语法更新包含N列的表中的N-1列的一些列。
我尝试的查询是这样的。
public T UpdatePost(Object DateUpdated, object DateExpires, object Id)
{
using (var session=sessionFactory.OpenSession())
{
using (var transaction=session.BeginTransaction())
{
session.Update(DateUpdated, Id);
session.Update(DateExpires, Id);
transaction.Commit();
return session.Get<T>(Id);
}
}
}
调用方法是
obj.UpdatePost(DateTime.Now, DateTime.Now.AddDays(30), 3);
错误是
您的映射存在问题。您可能正在尝试将System.ValueType映射到NHibernate不允许的地方,或者您错误地使用映射到a的IDictionary。 ValueType(System.DateTime)不能与IdentityKey一起使用。
如何实现这一目标?
答案 0 :(得分:2)
您的UpdatePost
方法毫无意义。 NHibernate的session.Update
期望一个应该更新的实体对象。您尝试使用的重载文档是:
更新与给定标识符关联的持久状态。
第一个参数应该是整个实体对象。
如果您尝试分析代码,NHibernate无法知道您要更新哪个实体。 Update
方法不是通用的,Session
也不是。你只是想给它一个日期值和一个id。 NHibernate将如何知道要更新哪个表和哪个列?
为了使用NHibernate进行部分更新,您需要使用HQL update queries(DML样式的操作)。
以下是您的情况:
public T UpdatePost(Object DateUpdated, object DateExpires, object Id)
{
using (var session=sessionFactory.OpenSession())
{
using (var transaction=session.BeginTransaction())
{
string hqlUpdate =
"update Post p set p.DateUpdated = :dateUpdated, p.DateExpires = :dateExpires where p.id = :id";
session.CreateQuery(hqlUpdate)
.SetDateTime("dateUpdated", DateUpdated)
.SetDateTime("dateExpires", DateExpires)
.SetParameter("id", Id)
.ExecuteUpdate();
transaction.Commit();
return session.Get<T>(Id);
}
}
}
另外,由于您在更新后已经获得了实体,因此您可以先加载实体,更改其属性并保存。您仍然可以进行两次数据库操作。
public T UpdatePost(DateTime DateUpdated, DateTime DateExpires, object Id)
{
using (var session=sessionFactory.OpenSession())
{
using (var transaction=session.BeginTransaction())
{
T post = session.Get<T>(Id);
post.DateUpdated = DateUpdated;
post.DateExpires = DateExpires;
session.Update(post);
transaction.Commit();
return post;
}
}
}
如果确实想强制NHibernate仅更新已更改的列,则可以在class mapping declaration中指定dynamic-update =“true”。
dynamic-update(可选,默认为false):指定应在运行时生成UPDATE SQL,并且仅包含值已更改的列。
答案 1 :(得分:0)
这将是最佳解决方案,因为SetDateTime仅接受DateTime类型作为其参数值。虽然一般地声明这种方法,但我们必须根据其实体类型格式化查询。
public T UpdatePost(DateTime DateUpdated, DateTime DateExpires, object Id) <-- DateTime parameters
{
using (var session = sessionFactory.OpenSession())
{
using (var transaction = session.BeginTransaction())
{
string hqlUpdate = string.Format(
"update {0} p set p.DateUpdated = :dateUpdated, p.DateExpires = :dateExpires where p.id = :id", typeof(T)); <-- passing the type of the entity.
session.CreateQuery(hqlUpdate)
.SetDateTime("dateUpdated",DateUpdated)
.SetDateTime("dateExpires", DateExpires)
.SetParameter("id", Id)
.ExecuteUpdate();
transaction.Commit();
return session.Get<T>(Id);
}
}
}