Example #1
0
        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;
            }
        }
Example #4
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);
		}
Example #5
0
		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;
		}