4

私はNHibernateリポジトリを持っています。UpdateNHibernate でロードされたオブジェクトとアンロードされたオブジェクトの両方でメソッドを呼び出したいですISession

しかし、この例外が発生します。これはMerge、の代わりにメソッドを呼び出す必要があることを意味しUpdateます。

同じ識別子値を持つ別のオブジェクトが、エンティティ: Eshop.Entities.Currency のセッション: 0adc76b1-7c61-4179-bb39-a05c0152f1a1 に既に関連付けられていました。

この例外を回避するためにリポジトリを一般化するにはどうすればよいですか?

ここに私の一般的なリポジトリがあります:

public class NHibernateProvider : IDataProvider
{
    #region Variables

    private readonly object locker = new object();
    private ISessionFactory sessionFactory;
    private Configuration configuration;
    private ITransaction transaction;

    #endregion

    #region Properties

    private ISessionFactory SessionFactory
    {
        get
        {
            lock (locker)
            {
                if (Null.IsObjectNull(HttpContext.Current.Items["DataProvider"]))
                {
                    configuration = new Configuration();

                    configuration.Configure();

                    HttpContext.Current.Items["DataProvider"] = sessionFactory = configuration.BuildSessionFactory();

                    HttpContext.Current.Items["DataProviderSession"] = sessionFactory.OpenSession();
                }

                return (HttpContext.Current.Items["DataProvider"] as ISessionFactory);
            }
        }
    }

    private ISession session;
    private ISession Session
    {
        get
        {
            if (Null.IsObjectNull(HttpContext.Current.Items["DataProviderSession"]))
            {
                session = SessionFactory.OpenSession();

                session.FlushMode = FlushMode.Auto;

                HttpContext.Current.Items["DataProviderSession"] = session;
            }
            else
            {
                session = HttpContext.Current.Items["DataProviderSession"] as ISession;
            }
            return session;

        }
    }

    #endregion

    #region Methods


    public T Get<T>(Guid ID)
    {
        return Session.Get<T>(ID);
    }

    public T Get<T>(Expression<Func<T, bool>> predicate)
    {
        return Session.Query<T>().Where(predicate).FirstOrDefault();
    }

    public IQueryable<T> GetAll<T>()
    {
        return Session.Query<T>();
    }

    public IQueryable<T> GetAll<T>(Expression<Func<T, bool>> predicate)
    {
        return Session.Query<T>().Where(predicate);
    }

    public IQueryable<T> GetAll<T>(Expression<Func<T, bool>> predicate, int currentPage, int pageSize
                                  )
    {
        if (Session.Query<T>().Any(predicate))
        {
            return Session.Query<T>().Where(predicate).Skip<T>(currentPage*pageSize).Take(pageSize);
        }
        return new List<T>().AsQueryable();
    }

    public IQueryable<T> GetAll<T, TKey>(Expression<Func<T, bool>> predicate, int currentPage, int pageSize,
                                         Expression<Func<T, TKey>> sortExpression)
    {
        if (Session.Query<T>().Any(predicate))
        {
            return
                Session.Query<T>().Where(predicate).Skip<T>(currentPage*pageSize).Take(pageSize).OrderBy<T, TKey>(
                    sortExpression);
        }
        return new List<T>().AsQueryable();
    }

    public bool Exists<T>(Guid ID)
    {
        if (Null.IsNotObjectNull(Session.Get<T>(ID)))
        {
            return true;
        }
        return false;

    }

    public bool Exists<T>(Expression<Func<T, bool>> predicate)
    {
        return Session.Query<T>().Where(predicate).Any();
    }

    public void Update<T>(T targetObject, bool commit = true) where T:class
    {
        try
        {
            BeginTransaction();

            Session.Update(targetObject);

            CommitTransaction(commit);


        }
        catch (Exception)
        {
            RollBackTransaction();
            throw;
        }
    }

    public void Update<T>(IEnumerable<T> targetObjects, bool commit = true) where T : class
    {
        try
        {
            BeginTransaction();

            foreach (var target in targetObjects)
            {
                Session.Update(target);
            }

            CommitTransaction(commit);


        }
        catch (Exception)
        {
            RollBackTransaction();
            throw;
        }
    }

    public void Insert<T>(T targetObject, bool commit = true)
    {
        try
        {
            BeginTransaction();

            Session.Save(targetObject);
            CommitTransaction(commit);

        }
        catch (Exception)
        {
            RollBackTransaction();
            throw;
        }
    }



    public void Insert<T>(IEnumerable<T> targetObject, bool commit = true)
    {
        foreach (T target in targetObject)
        {
            Insert<T>(target, false);
        }
        CommitTransaction(commit);
    }


    public void Delete<T>(T targetObject, bool commit = true)
    {
        try
        {
            BeginTransaction();

            Session.Delete(targetObject);
            CommitTransaction(commit);
        }
        catch (Exception)
        {
            RollBackTransaction();
            throw;
        }
    }

    public void Delete<T>(Guid targetID, bool commit = true)
    {
        try
        {
            BeginTransaction();

            Session.Delete(Get<T>(targetID));

            CommitTransaction(commit);
        }
        catch (Exception)
        {
            RollBackTransaction();
            throw;
        }
    }


    public void Delete<T>(Expression<Func<T, bool>> predicate, bool commit = true)
    {
        try
        {
            BeginTransaction();
            if (Session.Query<T>().Any(predicate))
            {
                foreach (T element in Session.Query<T>().Where(predicate))
                {
                    Session.Delete(element);
                }
            }
            CommitTransaction(commit);
        }
        catch (Exception)
        {
            RollBackTransaction();
            throw;
        }
    }

    private void RollBackTransaction()
    {
        transaction.Rollback();
    }

    private void CommitTransaction(bool commit)
    {
        if (commit && transaction.IsActive )
        {
            transaction.Commit();
        }
    }


    private void BeginTransaction()
    {
        if (Session.Transaction.IsActive == false)
        {
             transaction =Session.BeginTransaction();
        }
    }

    #endregion

}
4

2 に答える 2

3

Merge は、NHibernate セッションでの状態 (デタッチ、永続) を考慮してエンティティをマージまたは更新することを決定するため、 Merge を使用する必要があることがわかりました。

于 2012-05-26T08:57:09.783 に答える