Beispiel #1
0
        /// <summary>
        /// Mark property as not updatable. Not updatable properties
        /// will not be updated after inserted. Not updatable properties
        /// will not be checked against database to define if value of property
        /// has been changed.
        /// </summary>
        /// <exception cref="ArgumentException">
        /// When not appropriate or already marked property is marked.
        /// </exception>
        /// <returns>Current ExtendedPropertyHelper.</returns>
        public ExtendedPropertyHelper <T> NotUpdatable()
        {
            var sourceType = typeof(T);

            if (!Property.PropertyType.GetUnderlyingType().IsBuiltinType())
            {
                throw new ArgumentException(string.Format(
                                                "Property '{0}' for '{1}' is inappropriate property to set as not updatable.\n" +
                                                "Only properties underlying type of which is built in types can be set as not updatable.",
                                                Property.Name,
                                                typeof(T).Name));
            }

            var markedNotUpdatable =
                MappingStorage.Instance.NotUpdatableProperties
                .Where(m => m.SourceType.Equals(typeof(T)))
                .FirstOrDefault();

            if (markedNotUpdatable == null)
            {
                markedNotUpdatable = new PropertiesWithSource()
                {
                    SourceType = typeof(T)
                }
            }
            ;

            var alreadyAdded = markedNotUpdatable.Properties
                               .Any(m => Property.Name.Equals(m.Name));

            if (alreadyAdded)
            {
                return(this);
            }

            markedNotUpdatable.Properties.Add(Property);

            if (!MappingStorage.Instance.NotUpdatableProperties.Contains(markedNotUpdatable))
            {
                MappingStorage.Instance.NotUpdatableProperties.Add(markedNotUpdatable);
            }

            return(this);
        }
    }
Beispiel #2
0
        /// <summary>
        /// Mark properties as unique.
        /// </summary>
        /// <exception cref="ArgumentNullException">
        /// When lambda expression is null.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// When lambda expression deos not select any property.
        /// When lambda expression selects not appropriate properties.
        /// When lambda expression selects already selected combination
        /// of properties to set as unique.
        /// </exception>
        /// <typeparam name="TProperty">Type of property.</typeparam>
        /// <param name="propertyLambda">Lambda expression to mark properties as unique.</param>
        public void HasUnique <TProperty>(
            Expression <Func <TEntity, TProperty> > propertyLambda)
        {
            if (propertyLambda == null)
            {
                throw new ArgumentNullException("propertyLambda");
            }

            var markedProperties = propertyLambda.GetPropertyInfoList();

            if (markedProperties == null ||
                markedProperties.Count == 0)
            {
                throw new ArgumentException(string.Format(
                                                "Expression '{0}' for '{1}' marks no property to set as unique",
                                                propertyLambda.ToString(),
                                                typeof(TEntity).Name));
            }

            // Selects properties which are not appropriate to set as unique
            var violatedProperties = markedProperties
                                     .Where(m => m.PropertyType.IsCollectionType() ||
                                            (!m.PropertyType.IsBuiltinType() &&
                                             (!m.PropertyType.IsEnum &&
                                              !m.PropertyType.IsNullableEnum())));


            if (violatedProperties != null &&
                violatedProperties.Count() > 0)
            {
                throw new ArgumentException(string.Format(
                                                "Expression '{0}' for '{1}' selects inappropriate properties to set unique.\n" +
                                                "Only built in value types or enums can be set as unique.",
                                                propertyLambda.ToString(),
                                                typeof(TEntity).Name));
            }

            var markedAsUnique = new PropertiesWithSource()
            {
                SourceType = typeof(TEntity),
                Properties = markedProperties
            };

            var duplicates = MappingStorage.Instance.UniqueProperties
                             .Where(m => m.SourceType.Equals(markedAsUnique.SourceType) &&
                                    m.Properties
                                    .Select(p => p.Name)
                                    .OrderBy(p => p)
                                    .SequenceEqual(markedAsUnique
                                                   .Properties
                                                   .Select(p => p.Name)
                                                   .OrderBy(p => p)));

            if (duplicates.Any())
            {
                return;
            }

            if (!MappingStorage.Instance.UniqueProperties.Contains(markedAsUnique))
            {
                MappingStorage.Instance.UniqueProperties.Add(markedAsUnique);
            }
        }
Beispiel #3
0
        /// <summary>
        /// Mark properties state of which has to be defined before entity itself
        /// in order to be able to correctly define state of entity itself. These properties
        /// are those uniqueness of which can be determined easily according to their
        /// property values. Properties from which state of entity is dependant from
        /// and which are in one-to-one relationship with this entity should be marked.
        /// Parents of entity or entities which are in many-to-one relationship with this entity
        /// should not be marked, they are automatically ordered.
        /// </summary>
        /// <exception cref="ArgumentNullException">
        /// When lambda expression is null.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// When lambda expression selects no property at all.
        /// When lambda expression selects inappropriate properties to define state of.
        /// When lambda expression selects already selected property to define state of.
        /// </exception>
        /// <typeparam name="TProperty">Type of property.</typeparam>
        /// <param name="propertyLambda">Lambda expression to get properties
        /// state of which must be defined.</param>
        public void HasStateDefiner <TProperty>(
            Expression <Func <TEntity, TProperty> > propertyLambda)
        {
            if (propertyLambda == null)
            {
                throw new ArgumentNullException("propertyLambda");
            }

            var markedProperties = propertyLambda.GetPropertyInfoList();

            if (markedProperties == null ||
                markedProperties.Count == 0)
            {
                throw new ArgumentException(string.Format(
                                                "Expression '{0}' for '{1}' marks no property to define state of",
                                                propertyLambda.ToString(),
                                                typeof(TEntity).Name));
            }

            // Selects properties which are not appropriate to set as to define sate of
            var violatedProperties = markedProperties
                                     .Where(m => m.PropertyType.IsValueType ||
                                            (m.PropertyType.IsBuiltinType() &&
                                             m.PropertyType.IsCollectionType() &&
                                             m.PropertyType.IsGenericType &&
                                             (m.PropertyType
                                              .GenericTypeArguments
                                              .FirstOrDefault()
                                              .IsBuiltinType() ||
                                              !m.PropertyType
                                              .GenericTypeArguments
                                              .FirstOrDefault()
                                              .IsClass)));

            if (violatedProperties != null &&
                violatedProperties.Count() > 0)
            {
                throw new ArgumentException(string.Format(
                                                "Expression '{0}' for '{1}' selects inappropriate properties to define state of.\n" +
                                                "Only properties of user defined class type or collections of those classes" +
                                                "can be set to define state of",
                                                propertyLambda.ToString(),
                                                typeof(TEntity).Name));
            }


            var markedToDefineStateOf = MappingStorage.Instance.StateDefiners
                                        .Where(m => m.SourceType.Equals(typeof(TEntity)))
                                        .FirstOrDefault();

            if (markedToDefineStateOf == null)
            {
                markedToDefineStateOf = new PropertiesWithSource()
                {
                    SourceType = typeof(TEntity)
                }
            }
            ;


            var alreadyAdded = markedToDefineStateOf.Properties
                               .Any(m => markedProperties
                                    .Select(p => p.Name)
                                    .Contains(m.Name));

            if (alreadyAdded)
            {
                return;
            }

            markedToDefineStateOf.Properties.AddRange(markedProperties);

            if (!MappingStorage.Instance.StateDefiners.Contains(markedToDefineStateOf))
            {
                MappingStorage.Instance.StateDefiners.Add(markedToDefineStateOf);
            }
        }
        /// <summary>
        /// Compare entity and entity from source and detect which properties
        /// have been changed. Prepare changed proeprties for update.
        /// </summary>
        /// <exception cref="ArgumentNullException">
        /// When entity or entityFromSource is null.
        /// </exception>
        /// <param name="entity">Current entity to compare.</param>
        /// <param name="entityFromSource">Entity from source to compare.</param>
        /// <returns>True if any of propeties has been changed/False otherwise.</returns>
        public bool DetectPropertyChanges(
            TEntity entity,
            TEntity entityFromSource)
        {
            if (entity == null)
            {
                throw new ArgumentNullException(nameof(entity));
            }
            if (entityFromSource == null)
            {
                throw new ArgumentNullException(nameof(entityFromSource));
            }

            bool anyPropertyHasChanged = false;

            IEnumerable <string> primaryKeyNames = GetPrimaryKeys();

            PropertiesWithSource notToCompareConfiguration = MappingStorage
                                                             .Instance
                                                             .PropertiesNotToCompare
                                                             .Where(m => m.SourceType.Equals(typeof(TEntity)))
                                                             .FirstOrDefault();

            PropertiesWithSource notUpdatableConfiguration = MappingStorage
                                                             .Instance
                                                             .NotUpdatableProperties
                                                             .Where(m => m.SourceType.Equals(typeof(TEntity)))
                                                             .FirstOrDefault();

            IEnumerable <string> propertiesNotToCompare;
            IEnumerable <string> notUpdatableProperties;

            if (notToCompareConfiguration != null)
            {
                propertiesNotToCompare = notToCompareConfiguration
                                         .Properties
                                         .Select(m => m.Name);
            }
            else
            {
                propertiesNotToCompare = new List <string>();
            }

            if (notUpdatableConfiguration != null)
            {
                notUpdatableProperties = notUpdatableConfiguration
                                         .Properties
                                         .Select(m => m.Name);
            }
            else
            {
                notUpdatableProperties = new List <string>();
            }


            // Get properties to compare
            List <string> propertiesToCompare = GetSimpleEntityProperties()
                                                .Where(m => !primaryKeyNames.Contains(m.Name) &&
                                                       !propertiesNotToCompare.Contains(m.Name) &&
                                                       !notUpdatableProperties.Contains(m.Name))
                                                .Select(m => m.Name)
                                                .ToList();

            DbEntityEntry <TEntity> entry = Context.Entry(entity);

            foreach (string propertyName in propertiesToCompare)
            {
                var currentValue = entity.GetPropertyValue(propertyName);
                var sourceValue  = entityFromSource.GetPropertyValue(propertyName);

                if (!Utilities.IsEqual(
                        entity.GetPropertyValue(propertyName),
                        entityFromSource.GetPropertyValue(propertyName)))
                {
                    anyPropertyHasChanged = true;

                    entry.Property(propertyName).IsModified = true;
                }
            }

            // If any properties has changed also update
            // properties which marked not to compare
            if (anyPropertyHasChanged)
            {
                foreach (string propertyName in propertiesNotToCompare.Except(notUpdatableProperties))
                {
                    Context.Entry(entity)
                    .Property(propertyName).IsModified = true;
                }
            }

            return(anyPropertyHasChanged);
        }