C# 使用QueryOver更新N列表的N-1列<;T>;()方法

C# 使用QueryOver更新N列表的N-1列<;T>;()方法,c#,nhibernate,queryover,C#,Nhibernate,Queryover,我只想使用NHibernate QueryOver语法更新包含N列的表中的一些列,比如N-1列 我尝试的查询是这样的 public T UpdatePost(Object DateUpdated, object DateExpires, object Id) { using (var session=sessionFactory.OpenSession()) { using (var transaction=session.

我只想使用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);
            }
        }
    }
错误是

您的映射有问题。您可能正在尝试将System.ValueType映射到NHibernate不允许的,或者您错误地使用了映射到的IDictionary。ValueType(System.DateTime)不能与IdentityKey一起使用


如何实现这一点?

您的
UpdatePost
方法毫无意义。NHibernate的
会话.Update
需要一个应该更新的实体对象。您尝试使用的重载的文档是:

更新与给定标识符关联的持久状态

第一个参数应该是整个实体对象

如果您试图分析代码,NHibernate就无法知道要更新哪个实体<代码>更新方法不是泛型的,
会话
也不是泛型的。您只是想给它一个日期值和一个id。NHibernate如何知道要更新哪个表和哪个列

为了对NHibernate进行部分更新,您需要使用(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(对象DateUpdated、对象DateExpires、对象Id)
{
使用(var session=sessionFactory.OpenSession())
{
使用(var transaction=session.BeginTransaction())
{
字符串hqlUpdate=
“更新Post p set p.DateUpdated=:DateUpdated,p.DateExpires=:DateExpires,其中p.id=:id”;
会话.CreateQuery(hqlUpdate)
.SetDateTime(“dateUpdated”,dateUpdated)
.SetDateTime(“dateExpires”,dateExpires)
.SetParameter(“id”,id)
.ExecuteUpdate();
Commit();
返回会话.Get(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;
        }
    }
}
public T UpdatePost(DateTime DateUpdated,DateTime DateExpires,对象Id)
{
使用(var session=sessionFactory.OpenSession())
{
使用(var transaction=session.BeginTransaction())
{
T post=session.Get(Id);
post.DateUpdated=DateUpdated;
post.DateExpires=DateExpires;
更新(员额);
Commit();
回程站;
}
}
}
如果确实要强制NHibernate仅更新已更改的列,可以在中指定dynamic update=“true”

动态更新(可选,默认为false):指定应在运行时生成更新SQL,并仅包含值已更改的列


这将是最佳解决方案,因为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);
                }
            }
        }

public T UpdatePost(DateTime-DateUpdated,DateTime-DateExpires,object-Id)在Miroslav中,SetDateTime方法在传递DateUpdated,DateExpires时不接受对象作为参数值。
public T-UpdatePost(object-DateUpdated,object-DateExpires,object-Id)
但是我一般地声明方法,我们必须提供实体的类型。您的第二个解决方案适用于特定于实体的存储库。请看我的答案,这是我在谷歌搜索了几个小时后发现的。啊,好的。。。您可能尝试过使用
.SetParameter()
来代替。在您的域中
Post
是基类吗?不确定为什么该方法同时命名为
UpdatePost
和泛型。Post不是基类。这就是为什么我删除了post并将其格式化为typeof(T),即它对应于每个实体。在我的数据库中,每个表(实体)都包含DateUpdated和DateExpires列。这就是为什么我要在存储库级别而不是实体级别编写updatepost方法。这一功能只是两次更新,但没有其他列受到影响。
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);
                }
            }
        }