I've run into some trouble with unique constraints in NHibernate.
I have a User entity that is mapped with a unique constraint for the Username property. What I want to do is to be able to check if a particular username exists before a new user is added and also before an existing user updates it's username.
The first scenario (adding a new user) works just fine. However, when I try to check if the username exists before updating an existing user, I get a constraint violation. Here's what the code for my Save method looks like.
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;
}
}
}
The constraint is violated in the CheckIfUsernameExists() method and it looks like this:
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;
}
It is the session.CreateCriteria() line that causes it to crash resulting in an NHibernateException (SQLiteException) with the message "Abort due to constraint violation. column Username is not unique".
Is it related to the NHibernate cash? The entity that is passed to the save method has been updated with the desired username at the time session.CreateCriteria() is called.
Maybe I'm doing this all wrong (I am an NHibernate beginner) so please feel free to state the obvious and suggest alternatives.
Any help is much appreciated!