protected override void LockCore(DomainObject obj, DirtyState dirtyState) { if (dirtyState != DirtyState.Clean) throw new InvalidOperationException(); this.Session.Lock(obj, LockMode.None); }
private static HqlQuery BuildQuery(DomainObject obj, Type entityClass, string[] uniqueConstraintMembers) { // get the id of the object being validated // if the object is unsaved, this id may be null var id = (obj is Entity) ? ((Entity) obj).OID : ((EnumValue) obj).Code; var query = new HqlQuery(string.Format("select count(*) from {0} x", entityClass.Name)); if (id != null) { // this object may have already been saved (i.e. this is an update) and therefore should be // excluded query.Conditions.Add(new HqlCondition("x.id <> ?", new [] { id })); } // add other conditions foreach (var propertyExpression in uniqueConstraintMembers) { var value = EvaluatePropertyExpression(obj, propertyExpression); if (value == null) query.Conditions.Add(new HqlCondition(string.Format("x.{0} is null", propertyExpression), new object[] { })); else query.Conditions.Add(new HqlCondition(string.Format("x.{0} = ?", propertyExpression), new [] { value })); } return query; }
/// <summary> /// Tests whether the specified object satisfies the specified unique constraint. /// </summary> /// <param name="obj">The object to test.</param> /// <param name="entityClass">The class of entity to which the constraint applies.</param> /// <param name="uniqueConstraintMembers">The properties of the object that form the unique key. /// These may be compound property expressions (e.g. Name.FirstName, Name.LastName). /// </param> /// <returns></returns> public bool IsUnique(DomainObject obj, Type entityClass, string[] uniqueConstraintMembers) { Platform.CheckForNullReference(obj, "obj"); Platform.CheckForNullReference(entityClass, "entityClass"); Platform.CheckForNullReference(uniqueConstraintMembers, "uniqueConstraintMembers"); if (uniqueConstraintMembers.Length == 0) throw new InvalidOperationException("uniqueConstraintMembers must contain at least one entry."); var hqlQuery = BuildQuery(obj, entityClass, uniqueConstraintMembers); // create a new session to do the validation query // this is a bit of a HACK, but we know that this may occur during an interceptor callback // on the originating session, and we don't want to modify the state of that session // ideally the new session should share the connection and transaction of the main session, // but this isn't possible with NHibernate 1.2.0 using (var auxSession = this.Context.PersistentStore.SessionFactory.OpenSession()) { // since we are forced to use a separate transaction, use ReadUncommitted isolation level // we want to avoid deadlocking here at all costs, even if it means dirty reads // the worst the can happen with a dirty read is that validation will be incorrect, // but that's not the end of the world, because the DB will still enforce uniqueness var tx = auxSession.BeginTransaction(IsolationLevel.ReadUncommitted); auxSession.FlushMode = FlushMode.Never; var query = auxSession.CreateQuery(hqlQuery.Hql); var i = 0; foreach (var condition in hqlQuery.Conditions) { foreach(var paramVal in condition.Parameters) query.SetParameter(i++, paramVal); } var count = query.UniqueResult<long>(); tx.Commit(); // no data will be written (Flushmode.Never, and we didn't write anything anyways) // if count == 0, there are no other objects with this particular set of values return count == 0; } }
private void CheckRequiredFields(DomainObject entity) { // This is really a HACK // we need to test the required field rules before NHibernate gets a chance to complain about them // in order to provide more descriptive error message (the NHibernate error messages aren't as nice as ours) _validator.ValidateRequiredFieldsPresent(entity); }
protected override void LockCore(DomainObject obj, DirtyState dirtyState) { switch (dirtyState) { case DirtyState.Dirty: Session.Update(obj); break; case DirtyState.New: CheckRequiredFields(obj); Session.Save(obj); break; case DirtyState.Clean: Session.Lock(obj, LockMode.None); break; } }
private static bool IsChangeSetPublishable(DomainObject domainObject) { // ignore changes to enum values for now // TODO: should probably record changes to enum values if (domainObject is EnumValue) return false; // check for an attribute - if no attribute, then default is publishable var a = AttributeUtils.GetAttribute<PublishInChangeSetsAttribute>(domainObject.GetClass(), true); return a == null || a.IsPublishable; }