NHibernate独特的约束

时间:2009-09-25 10:09:15

标签: nhibernate fluent-nhibernate

我遇到了NHibernate中唯一约束的麻烦。

我有一个User实体,它使用Username属性的唯一约束进行映射。我想要做的是能够在添加新用户之前以及在现有用户更新其用户名之前检查特定用户名是否存在。

第一个场景(添加新用户)工作得很好。但是,当我在更新现有用户之前尝试检查用户名是否存在时,我会遇到约束违规。以下是我的Save方法的代码。

public void Save<T>(T entity) where T : User
    {
        using (var session = GetSession())
        using (var transaction = session.BeginTransaction())
        {
            try
            {
                CheckIfUsernameExists(entity);

                session.SaveOrUpdate(entity);
                session.Flush();
                transaction.Commit();
            }
            catch (HibernateException)
            {
                transaction.Rollback();
                throw;
            }
        }
    }

在CheckIfUsernameExists()方法中违反了约束,它看起来像这样:

public void CheckIfUsernameExists<T>(T entity) where T : User
    {
        var user = GetUserByUsername(entity);
        if (user != null)
            throw new UsernameExistsException();
    }

    private T GetUserByUsername<T>(T entity) where T : User
    {
        var username = entity.Username;
        var idToExclude = entity.Id;

        var session = GetSession();

        var user = session.CreateCriteria<T>()
            .Add(Restrictions.Eq("Username", username))
            .Add(Restrictions.Not(Restrictions.IdEq(idToExclude)))
            .UniqueResult() as T;

        return user;
    }

session.CreateCriteria()行导致它崩溃,导致NHibernateException(SQLiteException),并显示消息“由于约束违规而中止。列用户名不是唯一的”。

它与NHibernate现金有关吗?传递给save方法的实体已在session会话时使用所需的用户名进行更新。调用了CreateCriteria()。

也许我这样做是错的(我是NHibernate的初学者)所以请随意说出明显的建议替代方案。

非常感谢任何帮助!

4 个答案:

答案 0 :(得分:0)

嗯,我不确定问题的核心,但是对于试图查看用户是否已经存在的策略,为什么需要“.UniqueResult()”?

难道你不能假设得到一个与该用户名匹配的用户列表,并且与当前用户的ID不相同(显然)。像我这样做的伪代码

public bool ExistsUsername(string username, int idToExclude)
{
   IList<User> usersFound = someNHibernateCriteria excluding entries that have id = idToExclude

   return (usersFound.Count > 0)
}

答案 1 :(得分:0)

两个想法: - 你为什么不只是SaveOrUpdate,看看你是否成功。这在你的场景中是不可能的吗? - 我见过你提到过SQLite。这是您真正的生产系统,还是您用于测试的东西。如果是这样,您是否检查过是否存在问题的SQLite,并且查询是否适用于功能齐全的DBMS? - SQLite经常会出现这类问题,因为它不支持各种约束......

答案 2 :(得分:0)

您确定CreateCriteria会抛出异常吗?因为,我不知道如何从select语句中获取SQLlite约束异常。我几乎做了同样的事情......

public bool NameAlreadyExists(string name, int? exclude_id)
{
    ICriteria crit = session.CreateCriteria<User>()
        .SetProjection(Projections.Constant(1))
        .Add(Restrictions.Eq(Projections.Property("name"), name));

    if (exclude_id.HasValue)
        crit.Add(Restrictions.Not(Restrictions.IdEq(exclude_id.Value)));

    return crit.List().Count > 0;
}

我会查看生成的sql的顺序,看看是什么导致它。如果该实体在该会话中加载,则可能在查询之前更新。

答案 3 :(得分:0)

transaction.Rollback()不会从会话缓存中删除您的实体,而是使用session.Evict()。

请参阅:   - https://www.hibernate.org/hib_docs/nhibernate/html/performance.html#performance-sessioncache