【问题标题】:Generic NHibernate repository Contains(TId id) method通用 NHibernate 存储库 Contains(TId id) 方法
【发布时间】:2012-06-20 15:07:13
【问题描述】:

我有一个使用 NHibernate 的通用存储库,其中 ID 的类型也是通用参数:

/// <summary>
/// Represents a common base class for repositories.
/// </summary>
/// <typeparam name="TEntity"> The type of the entity. </typeparam>
/// <typeparam name="TId"> The type of the ID of the entity. </typeparam>
public abstract class RepositoryBase<TEntity, TId> : IRepository<TEntity, TId> where TEntity : EntityBase<TEntity, TId>

在这种情况下,如何实现一个对 NHibernate 快速且可读的通用 Contains 方法?

public bool Contains(TId id)
{
    using (var session = NHibernateHelper.OpenSession())
    {
        // throws an excpetion that Equals is not supported
        return session.QueryOver<TEntity>().Where(e => e.Id.Equals(id)).RowCount() > 0;
    }
}

更新:

在我的情况下,NHibernate 已关闭延迟加载。

【问题讨论】:

  • 那会是什么样子? TId 是一个通用参数...
  • 标准标准 api 采用通用对象
  • 我认为您可以重新制定它以使用例如WhereRestrictionOn() 和 Restrictions.Eq() 避免提及 Equals。
  • 顺便说一句,在每个存储库方法中打开一个新会话通常是一个很大的禁忌,因为它会妨碍正确使用缓存、延迟加载和事务。

标签: c# nhibernate


【解决方案1】:

正如 cmets 所指出的...使用标准,使用“id”特殊属性

public bool Contains(TId id)
{
    using (var session = NHibernateHelper.OpenSession())
    { 
        return session.CreateCriteria(typeof(TEntity))
            .Add(Expression.Eq("id", id))
            .SetProjection( Projections.Count("id"))
            .UniqueResult() > 0
    }
}

【讨论】:

  • 好吧,我还不太熟悉 NHiberntate 的基础,但它怎么能不访问数据库来检查实体是否存在呢?只有数据库拥有所有实体。另外:GetById 不会花费更多时间,因为它会从数据库中加载整个实体,而我所有实际上它所要做的就是检查 ID 是否存在。
  • GetById 是这样实现的:session.Get&lt;TEntity&gt;(id) 这意味着它将获得 all 连接表 andall 列实例化聚合的所有个连接子对象。只是为了检查实体 (ID) 的存在,这难道不是矫枉过正吗?
  • 在我第一次回答时,没有关于延迟加载的编辑。
【解决方案2】:

我认为您必须在实体基类中覆盖 Eqauls 和其他比较运算符,例如:

public abstract class TEntity
{
    public override bool Equals(object entity)
    {
        return entity != null
            && entity is EntityBase
            && this == (EntityBase)entity;
    }

    public static bool operator ==(EntityBase base1, 
        EntityBase base2)
    {
        if ((object)base1 == null && (object)base2 == null)
        {
            return true;
        }

        if ((object)base1 == null || (object)base2 == null)
        {
            return false;
        }
        if (base1.Key != base2.Key)
        {
            return false;
        }

        return true;
    }
    public static bool operator !=(EntityBase base1, 
        EntityBase base2)
    {
        return (!(base1 == base2));
    }
}

【讨论】:

  • 我想我不应该有一个bool Contains(TEntity entity),而是一个bool Contains(TId id),因为如果NHibernate需要使用我的Entity类的.Equals,在最坏的情况下它必须从数据库中加载所有个实体并为每个调用TEntity.Equals
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-09
  • 1970-01-01
  • 2016-09-11
  • 1970-01-01
  • 1970-01-01
  • 2010-12-20
  • 2011-02-12
相关资源
最近更新 更多