13

这一定是一个简单的问题。给定一个标准,如何删除满足标准的实体?

理由:

HQL 和 NH 标准是 NHibernate 特定的构造,因此它们是服务器端 DAL 实现细节。我不希望他们“泄漏”到客户端。因此,我们的客户端提供了 LINQ 表达式供服务器处理。到目前为止,选择请求和 LINQ to NHibernate 处理它们的请求都很好。

但是,现在需要实现批量删除操作。像往常一样,客户端提供一个 LINQ 表达式,服务器将删除满足该表达式的实体。不幸的是,LINQ to NHibernate 在这里没有帮助。它最多只能将给定的 LINQ 表达式转换为 NHibernate 标准。

无论如何,这就是故事。我想强调的是,客户端根本不知道 NHibernate,我喜欢它保持这种状态。

附言

我正在使用 NH 2.1

4

4 回答 4

7

您可以使用标准来选择元素的 ID,将它们连接到一个字符串中并使用 HQL 删除它们吗?

就像是:

public void Delete(ICriteria criteria, string keyName, string tableName)
{
    criteria.setProjection(Projections.Attribute(keyName));
    IList<int> itemIds = criteria.List<int>();

    string collection = string.Join(",", Array.ConvertAll<int, string>(itemIds, Convert.ToString));

    Session.HQL(string.Format("delete from {0} where {1} in ({2})", tableName, keyName, collection);
}

这段代码没有经过测试或编译(特别是我不确定 HQL 部分),但我认为你明白了:由于投影,我们不获取整个对象,而只获取索引。

于 2010-06-18T09:44:29.527 回答
3

简而言之,直到 2.1.2 你都不能。

但是,如果您可以将 LINQ 表达式转换为 HQL(或将 ICriteria 转换为 HQL),那么您可以使用ISession.Delete()使用传递的 HQL 字符串的重载方法。

于 2010-06-18T10:13:28.490 回答
-3

在您的存储库/dao/persistencemanager/whatever 类中:

public IEnumerable<T> FindAll(DetachedCriteria criteria)

        {

            return criteria.GetExecutableCriteria(Session).List<T>();

        }

接着

public void Delete(DetachedCriteria criteria)

        {

            foreach (T entity in FindAll(criteria))

            {

                Delete(entity);

            }

        }

请参阅 Davy Brion 的文章使用 NHibernate 进行数据访问

编辑

据我所知,如果你想使用 Criteria,你需要加载对象并遍历它们以删除它们。或者使用 HQL 或将 SQL 传递给会话。

于 2009-08-25T09:01:33.600 回答
-5

我知道这是一个老问题,但为了争论;如果使用存储库模式,您可以声明一个删除方法,该方法执行以下操作:

public void Delete(System.Linq.Expressions.Expression<System.Func<TEntity, bool>> predicate)
{
    var entities = _session.Query<TEntity>().Where(predicate);
    foreach (var entity in entities)
        _session.Delete(entity);
}

请注意,代码使用表达式是为了使存储库接口足够通用,因此您还可以实现例如实体框架存储库。

于 2011-08-19T07:59:56.113 回答