Example #1
0
        public virtual void Update(Type entityType, object entity, IEnumerable <string> properties)
        {
            if (entity == null || properties.IsNullOrEmpty())
            {
                return;
            }
            Check.NotNull(entityType);
            entity = entity.CastTo(entityType);
            entity = entity.DuplicateWithNonNavigations(this.DbContext);

            DbSet         set   = this.DbContext.Set(entityType);
            DbEntityEntry entry = this.DbContext.FindEntry(entity, false);

            if (entry.State == EntityState.Detached)
            {
                set.Attach(entity);
            }
            entry.State = EntityState.Unchanged;

            var values = entity.ToDictionary();

            foreach (string name in properties)
            {
                DbPropertyEntry property = entry.Property(name);
                property.IsModified   = true;
                property.CurrentValue = values[name];
            }
        }
        /// <summary>
        /// Get PropertyEntry of source to work on.
        /// </summary>
        /// <exception cref="ArgumentNullException">
        /// When propertyLambda is null.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// When propertyLambda does not select a proeprty
        /// or when Entry has no relevant property.
        /// </exception>
        /// <typeparam name="TProperty">Type of property.</typeparam>
        /// <param name="propertyLambda">Lambda expression to get property.</param>
        /// <returns>Entry property helper to be able to work on property.</returns>
        public IEntryPropertyHelper <TProperty> Property <TProperty>(
            Expression <Func <T, TProperty> > propertyLambda)
        {
            if (propertyLambda == null)
            {
                throw new ArgumentNullException("propertyLambda");
            }

            PropertyInfo property = propertyLambda.GetPropertyInfo();

            if (property == null)
            {
                throw new ArgumentException(string.Format(
                                                "Expression '{0}' does not select any property.",
                                                propertyLambda.ToString()));
            }

            DbPropertyEntry propertyEntry = Entry.Property(property.Name);

            if (propertyEntry == null)
            {
                throw new ArgumentException(string.Format(
                                                "Entry does not have property with '{0}' name.",
                                                property.Name));
            }

            EntryPropertyHelper <TProperty> helper =
                new EntryPropertyHelper <TProperty>(propertyEntry);

            return(helper);
        }
 public LoggableProperty(DbPropertyEntry entry, Object originalValue)
 {
     PropertyName = entry.Name;
     OriginalValue = originalValue;
     CurrentValue = entry.CurrentValue;
     IsModified = entry.IsModified && !Equals(OriginalValue, CurrentValue);
 }
Example #4
0
        private bool ShouldSavePropertyHistory(DbPropertyEntry propertyEntry, PropertyInfo propertyInfo, ICollection <EdmProperty> complexTypeProperties, bool shouldSaveEntityHistory, bool defaultValue)
        {
            var shouldSavePropertyHistoryForInfo = ShouldSavePropertyHistoryForInfo(propertyInfo, shouldSaveEntityHistory);

            if (shouldSavePropertyHistoryForInfo.HasValue)
            {
                return(shouldSavePropertyHistoryForInfo.Value);
            }

            var isModified = false;

            if (propertyEntry is DbComplexPropertyEntry)
            {
                var complexProperty = complexTypeProperties.Single(t => t.Name == propertyInfo.Name);
                isModified = propertyEntry.As <DbComplexPropertyEntry>().HasChanged(complexProperty);
            }
            else
            {
                isModified = propertyEntry.HasChanged();
            }
            if (isModified)
            {
                return(true);
            }

            return(defaultValue);
        }
        public static DbEntityValidationResult RemoveEFFalseAlarms(this DbContext context, DbEntityValidationResult result,
                                                                   DbEntityEntry entityEntry)
        {
            IDirectUpdateContext directContext = context as IDirectUpdateContext;

            if (directContext != null)
            {
                DirectUpdateMode?mode = directContext.CurrentSaveOperationMode;

                if (mode.HasValue && mode.Value == DirectUpdateMode.AllowAll)
                {
                    List <DbValidationError> errorsToIgnore = new List <DbValidationError>();
                    foreach (DbValidationError error in result.ValidationErrors)
                    {
                        if (entityEntry.State == EntityState.Modified)
                        {
                            DbMemberEntry   member   = entityEntry.Member(error.PropertyName);
                            DbPropertyEntry property = member as DbPropertyEntry;
                            if (property != null)
                            {
                                if (!property.IsModified)
                                {
                                    errorsToIgnore.Add(error);
                                }
                            }
                        }
                    }

                    errorsToIgnore.ForEach(e => result.ValidationErrors.Remove(e));
                }
            }

            return(result);
        }
Example #6
0
 public LoggablePropertyEntry(DbPropertyEntry entry, Object originalValue)
 {
     IsModified         = entry.IsModified && !Object.Equals(originalValue, entry.CurrentValue);
     this.currentValue  = entry.CurrentValue;
     this.originalValue = originalValue;
     this.propertyName  = entry.Name;
 }
 public LoggableProperty(DbPropertyEntry entry, Object originalValue)
 {
     PropertyName  = entry.Name;
     OriginalValue = originalValue;
     CurrentValue  = entry.CurrentValue;
     IsModified    = entry.IsModified && !Equals(OriginalValue, CurrentValue);
 }
Example #8
0
        /// <summary>
        /// Creates an audit log entry for a <see cref="DbEntityEntry"/> that has an <see cref="EntityState"/> of <see cref="EntityState.Added"/> or <see cref="EntityState.Modified"/>
        /// It will create an audit log entry for each property that has changed
        /// </summary>
        private static AuditLog CreateAuditLogEntryForAddedOrModified(ObjectContext objectContext,
                                                                      DbEntityEntry dbEntry,
                                                                      string tableName,
                                                                      Person person,
                                                                      DateTime changeDate,
                                                                      AuditLogEventType auditLogEventType,
                                                                      DbPropertyEntry modifiedProperty)
        {
            var propertyName = modifiedProperty.Name;

            if (!string.Equals(propertyName, $"{tableName}ID", StringComparison.InvariantCultureIgnoreCase) && !string.Equals(propertyName, "TenantID", StringComparison.InvariantCultureIgnoreCase))
            {
                var optionalAuditDescriptionString = GetAuditDescriptionStringIfAnyForProperty(objectContext, dbEntry, propertyName, auditLogEventType);
                var auditLogEntry = CreateAuditLogEntryImpl(dbEntry,
                                                            tableName,
                                                            person,
                                                            changeDate,
                                                            auditLogEventType,
                                                            propertyName,
                                                            modifiedProperty.CurrentValue,
                                                            modifiedProperty.OriginalValue,
                                                            optionalAuditDescriptionString);
                return(auditLogEntry);
            }
            return(null);
        }
Example #9
0
        public int SaveChanges(string login)
        {
            // Get all Added/Deleted/Modified entities (not Unmodified or Detached)
            foreach (var e in ChangeTracker.Entries().Where(p => p.State == EntityState.Added || p.State == EntityState.Modified || p.Entity.GetType().GetProperty("RowVersion") != null))
            {
                if (e.State == EntityState.Added)
                {
                    if (e.Entity.GetType().GetProperty("CreateDate") != null)
                    {
                        DbPropertyEntry createDate = e.Property("CreateDate");
                        DbPropertyEntry createBy   = e.Property("CreateBy");

                        createDate.CurrentValue = DateTime.Now;
                        createBy.CurrentValue   = login;
                    }
                }
                else if (e.State == EntityState.Modified || (e.State == EntityState.Unchanged && e.Entity.GetType().GetProperty("RowVersion") != null))
                {
                    if (e.Entity.GetType().GetProperty("EditDate") != null)
                    {
                        DbPropertyEntry editDate = e.Property("EditDate");
                        DbPropertyEntry editBy   = e.Property("EditBy");

                        editDate.CurrentValue = DateTime.Now;
                        editBy.CurrentValue   = login;
                    }
                }
            }

            // Call the original SaveChanges(), which will save both the changes made and the audit records
            return(base.SaveChanges());
        }
Example #10
0
 public LoggableProperty(DbPropertyEntry entry, Object newValue)
 {
     NewValue   = newValue;
     Property   = entry.Name;
     OldValue   = entry.CurrentValue;
     IsModified = entry.IsModified && !Equals(NewValue, OldValue);
 }
 private static bool PropIsModified(DbPropertyEntry prop, IDbContext ctx)
 {
     // INFO: "CurrentValue" cannot be used for entities in the Deleted state.
     // INFO: "OriginalValues" cannot be used for entities in the Added state.
     //return !AreEqual(prop.CurrentValue, prop.OriginalValue);
     return(ctx.AutoDetectChangesEnabled
         ? prop.IsModified
         : !AreEqual(prop.CurrentValue, prop.OriginalValue));
 }
Example #12
0
        /// <summary>
        /// EntryProperty helper to work on property of entry.
        /// </summary>
        /// <exception cref="ArgumentNullException">
        /// When entryPropertyParam is null.
        /// </exception>
        /// <param name="entryPropertyParam">Entry proeprty to work on.</param>
        public EntryPropertyHelper(DbPropertyEntry entryPropertyParam)
        {
            if (entryPropertyParam == null)
            {
                throw new ArgumentNullException("entryPropertyParam");
            }

            EntryProperty = entryPropertyParam;
        }
        internal static object GetOriginalValue(this DbPropertyEntry propertyEntry)
        {
            if (propertyEntry.EntityEntry.State == EntityState.Added)
            {
                return(null);
            }

            return(propertyEntry.OriginalValue);
        }
        /// <summary>
        /// 获取实体历史
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="entity">实体对象</param>
        /// <returns>实体历史</returns>
        public IEntityHistory GetEntityHistory <T>(T entity) where T : PlainEntity
        {
            DbEntityEntry <T> entry = this._dbContext.ChangeTracker.Entries <T>().FirstOrDefault(x => x.Entity.Id == entity.Id);

            #region # 验证

            if (entry == null)
            {
                return(null);
            }

            #endregion

            LoginInfo  loginInfo = GetLoginInfo?.Invoke();
            ActionType actualActionType;
            IDictionary <string, object> beforeSnapshot = new Dictionary <string, object>();
            IDictionary <string, object> afterSnapshot  = new Dictionary <string, object>();
            if (entry.State == EntityState.Added)
            {
                actualActionType = ActionType.Create;
                foreach (string propertyName in entry.CurrentValues.PropertyNames)
                {
                    DbPropertyEntry propertyEntry = entry.Property(propertyName);
                    afterSnapshot[propertyName] = propertyEntry.CurrentValue;
                }
            }
            else if (entry.State == EntityState.Modified)
            {
                actualActionType = ActionType.Update;
                foreach (string propertyName in entry.OriginalValues.PropertyNames)
                {
                    DbPropertyEntry propertyEntry = entry.Property(propertyName);
                    if (propertyEntry.OriginalValue?.ToString() != propertyEntry.CurrentValue?.ToString())
                    {
                        beforeSnapshot[propertyName] = propertyEntry.OriginalValue;
                        afterSnapshot[propertyName]  = propertyEntry.CurrentValue;
                    }
                }
            }
            else if (entry.State == EntityState.Deleted)
            {
                actualActionType = ActionType.Delete;
                foreach (string propertyName in entry.OriginalValues.PropertyNames)
                {
                    DbPropertyEntry propertyEntry = entry.Property(propertyName);
                    beforeSnapshot[propertyName] = propertyEntry.OriginalValue;
                }
            }
            else
            {
                return(null);
            }

            EntityHistory entityHistory = new EntityHistory(actualActionType, typeof(T), entry.Entity.Id, beforeSnapshot, afterSnapshot, loginInfo?.LoginId, loginInfo?.RealName);

            return(entityHistory);
        }
        internal static object GetNewValue(this DbPropertyEntry propertyEntry)
        {
            if (propertyEntry.EntityEntry.State == EntityState.Deleted)
            {
                return(propertyEntry.OriginalValue);
            }

            return(propertyEntry.CurrentValue);
        }
Example #16
0
        /// <summary>	Sets the values. </summary>
        ///
        /// <exception cref="NotSupportedException">	Thrown when the requested operation is not
        ///                                             supported. </exception>
        ///
        /// <param name="dbEntry">      The database entry. </param>
        /// <param name="entry">	    The entry. </param>
        /// <param name="entityType">	Type of the entity. </param>
        private static void SetValues(DbEntityEntry dbEntry, DataModificationEntry entry, Type entityType)
        {
            if (entry.IsFullReplaceUpdate)
            {
                // The algorithm for a "FullReplaceUpdate" is taken from ObjectContextServiceProvider.ResetResource
                // in WCF DS, and works as follows:
                //  - Create a new, blank instance of the entity.
                //  - Copy over the key values and set any updated values from the client on the new instance.
                //  - Then apply all the properties of the new instance to the instance to be updated.
                //    This will set any unspecified properties to their default value.
                object newInstance = Activator.CreateInstance(entityType);

                SetValues(newInstance, entityType, entry.EntityKey);
                SetValues(newInstance, entityType, entry.LocalValues);

                dbEntry.CurrentValues.SetValues(newInstance);
            }
            else
            {
                foreach (KeyValuePair <string, object> propertyPair in entry.LocalValues)
                {
                    DbPropertyEntry propertyEntry = dbEntry.Property(propertyPair.Key);
                    object          value         = propertyPair.Value;
                    if (value == null)
                    {
                        // If the property value is null, we set null in the entry too.
                        propertyEntry.CurrentValue = null;
                        continue;
                    }

                    Type type = typeof(string);
                    if (propertyEntry.EntityEntry != null && propertyEntry.EntityEntry.Entity != null)
                    {
                        type = propertyEntry.EntityEntry.Entity.GetType().GetProperty(propertyPair.Key).PropertyType;
                    }
                    else if (propertyEntry.CurrentValue != null)
                    {
                        type = propertyEntry.CurrentValue.GetType();
                    }

                    if (propertyEntry is DbComplexPropertyEntry)
                    {
                        var dic = value as IReadOnlyDictionary <string, object>;
                        if (dic == null)
                        {
                            throw new NotSupportedException(string.Format("Unsupported type for property: {0}.", propertyPair.Key));
                        }

                        value = Activator.CreateInstance(type);
                        SetValues(value, type, dic);
                    }

                    propertyEntry.CurrentValue = ConvertToEfValue(type, value);
                }
            }
        }
        /// <summary>
        /// 获取实体历史列表
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="actionType">动作类型</param>
        /// <returns>实体历史列表</returns>
        public ICollection <IEntityHistory> GetEntityHistories <T>(ActionType?actionType = null) where T : PlainEntity
        {
            LoginInfo loginInfo = GetLoginInfo?.Invoke();
            ICollection <IEntityHistory>     entityHistories = new HashSet <IEntityHistory>();
            IEnumerable <DbEntityEntry <T> > entries         =
                from entry in this._dbContext.ChangeTracker.Entries <T>()
                where actionType == null || entry.State == (EntityState)actionType.Value
                select entry;

            foreach (DbEntityEntry <T> entry in entries)
            {
                ActionType actualActionType;
                IDictionary <string, object> beforeSnapshot = new Dictionary <string, object>();
                IDictionary <string, object> afterSnapshot  = new Dictionary <string, object>();
                if (entry.State == EntityState.Added)
                {
                    actualActionType = ActionType.Create;
                    foreach (string propertyName in entry.CurrentValues.PropertyNames)
                    {
                        DbPropertyEntry propertyEntry = entry.Property(propertyName);
                        afterSnapshot[propertyName] = propertyEntry.CurrentValue;
                    }
                }
                else if (entry.State == EntityState.Modified)
                {
                    actualActionType = ActionType.Update;
                    foreach (string propertyName in entry.OriginalValues.PropertyNames)
                    {
                        DbPropertyEntry propertyEntry = entry.Property(propertyName);
                        if (propertyEntry.OriginalValue?.ToString() != propertyEntry.CurrentValue?.ToString())
                        {
                            beforeSnapshot[propertyName] = propertyEntry.OriginalValue;
                            afterSnapshot[propertyName]  = propertyEntry.CurrentValue;
                        }
                    }
                }
                else if (entry.State == EntityState.Deleted)
                {
                    actualActionType = ActionType.Delete;
                    foreach (string propertyName in entry.OriginalValues.PropertyNames)
                    {
                        DbPropertyEntry propertyEntry = entry.Property(propertyName);
                        beforeSnapshot[propertyName] = propertyEntry.OriginalValue;
                    }
                }
                else
                {
                    continue;
                }

                EntityHistory entityHistory = new EntityHistory(actualActionType, typeof(T), entry.Entity.Id, beforeSnapshot, afterSnapshot, loginInfo?.LoginId, loginInfo?.RealName);
                entityHistories.Add(entityHistory);
            }

            return(entityHistories);
        }
Example #18
0
 public void SetUp()
 {
     using (TestingContext context = new TestingContext())
     {
         TestModel model = new TestModel();
         context.Set <TestModel>().Add(model);
         context.Entry(model).State = EntityState.Modified;
         entry = context.Entry(model).Property(property => property.Text);
     }
 }
Example #19
0
        public LoggablePropertyTests()
        {
            using (TestingContext context = new TestingContext())
            {
                TestModel model = new TestModel();

                context.Set <TestModel>().Attach(model);
                context.Entry(model).State = EntityState.Modified;
                textProperty = context.Entry(model).Property(prop => prop.Title);
                dateProperty = context.Entry(model).Property(prop => prop.CreationDate);
            }
        }
Example #20
0
 /// <summary>
 /// gets primary keys
 /// </summary>
 /// <param name="entry"></param>
 /// <returns></returns>
 private int?GetReleaseID(DbEntityEntry entry)
 {
     if (entry.GetDatabaseValues().PropertyNames.Contains("ReleaseID") == false)
     {
         return(null);
     }
     else
     {
         DbPropertyEntry releaseIDProperty = entry.Property("ReleaseID");
         return(Convert.ToInt32(releaseIDProperty.OriginalValue));
     }
 }
        public LoggablePropertyTests()
        {
            using (TestingContext context = new TestingContext())
            {
                Role model = ObjectFactory.CreateRole();

                context.Set <Role>().Add(model);
                context.Entry(model).State = EntityState.Modified;
                textProperty = context.Entry(model).Property(prop => prop.Title);
                dateProperty = context.Entry(model).Property(prop => prop.CreationDate);
            }
        }
        public LoggablePropertyTests()
        {
            using (TestingContext context = new TestingContext())
            {
                Role model = ObjectFactory.CreateRole();

                context.Set<Role>().Add(model);
                context.Entry(model).State = EntityState.Modified;
                textProperty = context.Entry(model).Property(prop => prop.Title);
                dateProperty = context.Entry(model).Property(prop => prop.CreationDate);
            }
        }
        protected override void ProcessEntities(IEnumerable <DbEntityEntry <Order> > entitesToProcess)
        {
            foreach (DbEntityEntry <Order> orderEntry in entitesToProcess)
            {
                DbPropertyEntry statusIdProperty = orderEntry.Property("StatusId");
                bool            isStatusChanged  = orderEntry.State != EntityState.Added && statusIdProperty.IsModified && ((int)statusIdProperty.OriginalValue) != ((int)statusIdProperty.CurrentValue);
                if (orderEntry.State == EntityState.Added || isStatusChanged)
                {
                    Order order = orderEntry.Entity;

                    order.OrderStatusesHistory.Add(new OrderStatusesHistory()
                    {
                        StatusId         = order.StatusId,
                        StatusAssignDate = DateTime.UtcNow
                    });
                }

                if (isStatusChanged)
                {
                    Order order       = orderEntry.Entity;
                    int   oldStatusId = (int)statusIdProperty.OriginalValue;
                    int   newStatusId = (int)statusIdProperty.CurrentValue;

                    MailSendingFacade mailSender = new MailSendingFacade();
                    mailSender.SendOrderStatusChangedMail(order.Id, oldStatusId, newStatusId);

                    if (newStatusId == 4) //Изпълнена
                    {
                        RegisterExpenseTask registerExpenseTask = new RegisterExpenseTask();
                        registerExpenseTask.Execute(new RegisterExpenseContext()
                        {
                            OrderId       = order.Id,
                            UserId        = order.UserId,
                            ExpenseAmount = order.TotalPrice
                        });
                    }
                }

                if (orderEntry.State == EntityState.Added)
                {
                    IEnumerable <ArticleOrderCountModel> articleOrderCounts = orderEntry.Entity.OrderDetails.Select(o =>
                                                                                                                    new ArticleOrderCountModel()
                    {
                        ArticleId  = o.ItemId,
                        OrderCount = o.Quantity
                    }).ToArray();

                    UpdateArticlesOrdersCountsTask updateArticlesOrdersCountsTask = new UpdateArticlesOrdersCountsTask();
                    updateArticlesOrdersCountsTask.Execute(articleOrderCounts);
                }
            }
        }
Example #24
0
File: UT2.cs Project: uwitec/mb-oa
        //[TestMethod]
        public void TestAttach()
        {
            LinkMethod lm = null;

            using (MyDBExt db = new MyDBExt())
            {
                lm = db.LinkMethods.Include(p => p.user).FirstOrDefault();
            }

            User user = null;

            using (MyDBExt db = new MyDBExt())
            {
                user = db.Users.FirstOrDefault(u => !u.Code.Equals(lm.user.ID));
            }

            lm.MethodType = "B";
            lm.user       = user;

            using (MyDBExt db = new MyDBExt())
            {
                // 附加到新上下文
                // 方法一
                //db.Entry(lm).State = System.Data.EntityState.Modified;
                //db.Entry<User>(lm.user).State = System.Data.EntityState.Modified;
                db.LinkMethods.Add(lm); // lm.user的状态也是Added,如果不把lm.user的状态设置为Unchanged,就会出现主键重复的错误
                db.Entry <LinkMethod>(lm).State = System.Data.EntityState.Modified;
                //db.Entry<User>(lm.user).State = System.Data.EntityState.Unchanged;

                DbReferenceEntry dre = db.Entry <LinkMethod>(lm).Reference(l => l.user);
                bool             x   = dre.IsLoaded;
                User             u   = lm.user;
                x = dre.IsLoaded;
                DbEntityEntry <LinkMethod> dee = db.Entry <LinkMethod>(lm);
                DbPropertyEntry            dpe = dee.Property(l => l.MethodType);


                //db.LinkMethods.Attach(lm);


                //lm.user = user;

                db.SaveChanges();
            }

            using (MyDBExt db = new MyDBExt())
            {
                IQueryable s = db.Users.Select(u => new { u, xX = db.LinkMethods.Where(l => l.user.ID.Equals(u.ID)).Count() });  // OK
                //IQueryable s = db.Users.Select(u => new { u, xX = db.LinkMethods.Where(l => l.user.ID.Equals(u.ID)).Select(l => l.MethodType) });  //NO
                //IQueryable s = db.Users.Select(u => new { u, xX = "ddddddddddddd" }); //OK
            }
        }
        internal static bool HasChanged(this DbPropertyEntry propertyEntry)
        {
            if (propertyEntry.EntityEntry.State == EntityState.Added)
            {
                return(propertyEntry.CurrentValue != null);
            }

            if (propertyEntry.EntityEntry.State == EntityState.Deleted)
            {
                return(propertyEntry.OriginalValue != null);
            }

            return(!(propertyEntry.OriginalValue?.Equals(propertyEntry.CurrentValue) ?? propertyEntry.CurrentValue == null));
        }
Example #26
0
        /// <summary>
        ///     update all changed records with current timestamp
        /// </summary>
        /// <param name="context">
        ///     The context.
        /// </param>
        public static void UpdateTimeStamps(this DbContext context)
        {
            // timestamp all changed
            DateTime now = DateTime.Now;

            foreach (DbEntityEntry entry in context.ChangeTracker.Entries())
            {
                if ((entry.State & EntityState.Unchanged) == EntityState.Unchanged)
                {
                    continue;
                }

                DbPropertyEntry property = entry.Property("ModifiedDate");
                if (property != null)
                {
                    property.CurrentValue = now;
                }
            }
        }
Example #27
0
        private static bool PropIsModified(DbPropertyEntry prop)
        {
            // TODO: "CurrentValues cannot be used for entities in the Deleted state."
            var cur = prop.CurrentValue;
            // TODO: "OriginalValues cannot be used for entities in the Added state."
            var orig = prop.OriginalValue;

            if (cur == null && orig == null)
            {
                return(false);
            }

            if (orig != null)
            {
                return(!orig.Equals(cur));
            }

            return(!cur.Equals(orig));
        }
Example #28
0
        private static void SetValues(DbEntityEntry dbEntry, DataModificationEntry entry, Type entityType)
        {
            if (entry.IsFullReplaceUpdate)
            {
                // The algorithm for a "FullReplaceUpdate" is taken from ObjectContextServiceProvider.ResetResource
                // in WCF DS, and works as follows:
                //  - Create a new, blank instance of the entity.
                //  - Copy over the key values and set any updated values from the client on the new instance.
                //  - Then apply all the properties of the new instance to the instance to be updated.
                //    This will set any unspecified properties to their default value.
                object newInstance = Activator.CreateInstance(entityType);

                SetValues(newInstance, entityType, entry.EntityKey);
                SetValues(newInstance, entityType, entry.LocalValues);

                dbEntry.CurrentValues.SetValues(newInstance);
            }
            else
            {
                foreach (KeyValuePair <string, object> propertyPair in entry.LocalValues)
                {
                    DbPropertyEntry propertyEntry = dbEntry.Property(propertyPair.Key);
                    object          value         = propertyPair.Value;

                    if (propertyEntry is DbComplexPropertyEntry)
                    {
                        var dic = value as IReadOnlyDictionary <string, object>;
                        if (dic == null)
                        {
                            // TODO GitHubIssue#103 : Choose property error message for unknown type
                            throw new NotSupportedException("Unsupported type for property:" + propertyPair.Key);
                        }

                        var type = propertyEntry.CurrentValue.GetType();
                        value = Activator.CreateInstance(type);
                        SetValues(value, type, dic);
                    }

                    propertyEntry.CurrentValue = ConvertToEfDateTimeIfValueIsEdmDate(value);
                }
            }
        }
Example #29
0
        //
        // only the changed field will be validate and update
        //
        bool checkModify(ref object row)
        {
            if (row == null)
            {
                return(false);
            }

            bool bResult = false;
            Type type    = THelper.GetBaseType(row);

            foreach (PropertyInfo pro in type.GetProperties())
            {
                if (PropertyHelper.IsVirtual(pro))
                {
                    if (PropertyHelper.HasElement(pro))
                    {
                        var value = pro.GetValue(row);
                        if (checkModify(ref value))
                        {
                            // set modify
                            pro.SetValue(row, value);
                            bResult = true;
                        }
                    }
                }
                else
                {
                    if (pro.Name == "id")
                    {
                        continue;
                    }
                    if (pro.GetValue(row) != null)
                    {
                        // set modify
                        DbPropertyEntry proEntry = m_db.Entry(row).Property(pro.Name);
                        proEntry.IsModified = true;
                        bResult             = true;
                    }
                }
            }
            return(bResult);
        }
Example #30
0
        private static bool PropIsModified(DbPropertyEntry prop, bool detectChangesEnabled, IDictionary <string, object> mergedProps)
        {
            var propIsModified = prop.IsModified;

            if (detectChangesEnabled && !propIsModified)
            {
                return(false);                // Perf
            }
            if (propIsModified && mergedProps != null && mergedProps.ContainsKey(prop.Name))
            {
                // EF "thinks" that prop has changed because merged value differs
                return(false);
            }

            // INFO: "CurrentValue" cannot be used for entities in the Deleted state.
            // INFO: "OriginalValues" cannot be used for entities in the Added state.
            return(detectChangesEnabled
                                ? propIsModified
                                : !AreEqual(prop.CurrentValue, prop.OriginalValue));
        }
        public static DbEntityValidationResult RemoveEFFalseAlarms(this DbContext context, DbEntityValidationResult result,
                                                                   DbEntityEntry entityEntry)
        {
            //This function doesn't do anything unless AllowAll is the mode

            IDirectUpdateContext directContext = context as IDirectUpdateContext;

            if (directContext != null)
            {
                UpdateMode?mode = directContext.CurrentSaveOperationMode;

                if (mode.HasValue && mode.Value == UpdateMode.Allow)
                {
                    List <DbValidationError> errorsToIgnore = new List <DbValidationError>();
                    foreach (DbValidationError error in result.ValidationErrors)
                    {
                        if (entityEntry.State == EntityState.Modified)
                        {
                            DbMemberEntry   member   = entityEntry.Member(error.PropertyName);
                            DbPropertyEntry property = member as DbPropertyEntry;
                            if (property != null)
                            {
                                if (!property.IsModified)
                                {
                                    //Add errors that resulted from not changing all the attributes
                                    errorsToIgnore.Add(error);
                                }
                            }
                        }
                    }
                    //Then the errors are ignored
                    errorsToIgnore.ForEach(e => result.ValidationErrors.Remove(e));
                }
            }

            return(result);
        }
Example #32
0
        public static List <EntityChange> ExtractChanges(DbContext context, IEnumerable <EntityChangeSource> sources)
        {
            var result = new List <EntityChange>();

            foreach (var source in sources)
            {
                if (source?.Entity == null)
                {
                    continue;
                }

                DbEntityEntry dbEntityEntry = context.Entry(source.Entity);
                if (dbEntityEntry.State != EntityState.Modified)
                {
                    continue;
                }

                string prefix = source.Prefix ?? "";

                foreach (string propName in dbEntityEntry.CurrentValues.PropertyNames)
                {
                    DbPropertyEntry dbPropertyEntry = dbEntityEntry.Property(propName);

                    if (dbPropertyEntry.IsModified)
                    {
                        result.Add(new EntityChange {
                            PropertyPath  = prefix + propName,
                            OriginalValue = dbPropertyEntry.OriginalValue,
                            ChangedValue  = dbPropertyEntry.CurrentValue
                        });
                    }
                }
            }

            return(result);
        }
        private void TestScalarOriginalValue(DbEntityEntry entityEntry, DbPropertyEntry<Building, string> propertyEntry,
                                             Type objectType, DbPropertyValues originalValues, string initialValue)
        {
            var initialState = entityEntry.State;

            if (initialState == EntityState.Added)
            {
                Assert.Throws<InvalidOperationException>(() => { var _ = propertyEntry.OriginalValue; }).ValidateMessage
                    ("DbPropertyValues_CannotGetValuesForState", "OriginalValues", "Added");
                Assert.Throws<InvalidOperationException>(() => propertyEntry.OriginalValue = "").ValidateMessage(
                    "DbPropertyValues_CannotGetValuesForState", "OriginalValues", "Added");
                return;
            }

            if (initialState == EntityState.Detached)
            {
                Assert.Throws<InvalidOperationException>(() => { var _ = propertyEntry.OriginalValue; }).ValidateMessage
                    ("DbPropertyEntry_NotSupportedForDetached", "OriginalValue", propertyEntry.Name,
                     entityEntry.Entity.GetType().Name);
                Assert.Throws<InvalidOperationException>(() => propertyEntry.OriginalValue = "").ValidateMessage(
                    "DbPropertyEntry_NotSupportedForDetached", "OriginalValue", propertyEntry.Name,
                    entityEntry.Entity.GetType().Name);
                return;
            }

            Assert.Equal(initialState == EntityState.Modified, propertyEntry.IsModified);
            Assert.Equal(initialValue, propertyEntry.OriginalValue);

            // Set to same value; prop should not get marked as modified
            propertyEntry.OriginalValue = initialValue;
            Assert.Equal(initialState == EntityState.Modified, propertyEntry.IsModified);
            Assert.Equal(initialState, entityEntry.State);

            // Set to new value; prop marked as modified
            propertyEntry.OriginalValue = "New Value";
            Assert.Equal("New Value", propertyEntry.OriginalValue);
            CheckPropertyIsModified(entityEntry, propertyEntry, initialState);

            // New value reflected in record
            Assert.Equal("New Value", originalValues[propertyEntry.Name]);

            // Change record; new value reflected in entry
            originalValues[propertyEntry.Name] = "Another Value";
            Assert.Equal("Another Value", propertyEntry.OriginalValue);

            // Set to null
            propertyEntry.OriginalValue = null;
            Assert.Equal(null, propertyEntry.OriginalValue);
        }
        private void TestScalarCurrentValue(DbEntityEntry entityEntry, DbPropertyEntry<Building, string> propertyEntry,
                                            DbPropertyValues currentValues, Func<string> getter, string initialValue)
        {
            var initialState = entityEntry.State;

            Assert.Equal(initialState == EntityState.Modified, propertyEntry.IsModified);
            Assert.Equal(initialValue, propertyEntry.CurrentValue);

            // Set to same value; prop should not get marked as modified
            propertyEntry.CurrentValue = initialValue;
            Assert.Equal(initialState == EntityState.Modified, propertyEntry.IsModified);
            Assert.Equal(initialState, entityEntry.State);

            // Set to new value; prop marked as modified
            propertyEntry.CurrentValue = "New Value";
            Assert.Equal("New Value", propertyEntry.CurrentValue);
            Assert.Equal("New Value", getter());
            CheckPropertyIsModified(entityEntry, propertyEntry, initialState);

            // New value reflected in record
            if (initialState != EntityState.Deleted && initialState != EntityState.Detached)
            {
                Assert.Equal("New Value", currentValues[propertyEntry.Name]);

                // Change record; new value reflected in entry
                currentValues[propertyEntry.Name] = "Another Value";
                Assert.Equal("Another Value", propertyEntry.CurrentValue);
                Assert.Equal("Another Value", getter());
            }

            // Set to null
            propertyEntry.CurrentValue = null;
            Assert.Null(propertyEntry.CurrentValue);
            Assert.Null(getter());
        }
 private void TestOriginalValueNotInModel(DbEntityEntry entityEntry,
                                          DbPropertyEntry<Building, string> propertyEntry)
 {
     Assert.Throws<InvalidOperationException>(() => { var _ = propertyEntry.OriginalValue; }).ValidateMessage(
         "DbPropertyEntry_NotSupportedForPropertiesNotInTheModel", "OriginalValue", propertyEntry.Name,
         entityEntry.Entity.GetType().Name);
     Assert.Throws<InvalidOperationException>(() => propertyEntry.OriginalValue = "").ValidateMessage(
         "DbPropertyEntry_NotSupportedForPropertiesNotInTheModel", "OriginalValue", propertyEntry.Name,
         entityEntry.Entity.GetType().Name);
 }
 private void TestIsModifiedNotInModel(DbEntityEntry entityEntry, DbPropertyEntry<Building, string> propertyEntry)
 {
     Assert.False(propertyEntry.IsModified);
     Assert.Throws<InvalidOperationException>(() => propertyEntry.IsModified = true).ValidateMessage(
         "DbPropertyEntry_NotSupportedForPropertiesNotInTheModel", "IsModified", propertyEntry.Name,
         entityEntry.Entity.GetType().Name);
 }
        private void TestCurrentValueNotInModel(DbEntityEntry entityEntry, DbPropertyEntry propertyEntry,
                                                Type objectType, Func<string> getter, string initialValue,
                                                bool hasGetter, bool hasSetter)
        {
            Assert.False(propertyEntry.IsModified);
            if (hasGetter)
            {
                Assert.Equal(initialValue, propertyEntry.CurrentValue);
            }
            else
            {
                Assert.Throws<InvalidOperationException>(() => { var _ = propertyEntry.CurrentValue; }).ValidateMessage(
                    "DbPropertyEntry_CannotGetCurrentValue", propertyEntry.Name, objectType.Name);
            }

            // Set to new value; prop still not modified because it is not in the model
            if (hasSetter)
            {
                propertyEntry.CurrentValue = "New Value";
                if (hasGetter)
                {
                    Assert.Equal("New Value", propertyEntry.CurrentValue);
                }
                Assert.Equal("New Value", getter());

                // Set to null
                propertyEntry.CurrentValue = null;
                Assert.Null(getter());
            }
            else
            {
                Assert.Throws<InvalidOperationException>(() => { propertyEntry.CurrentValue = ""; }).ValidateMessage(
                    "DbPropertyEntry_CannotSetCurrentValue", propertyEntry.Name, objectType.Name);
            }
            Assert.False(propertyEntry.IsModified);
        }
        private void TestIsModified(DbEntityEntry entityEntry, DbPropertyEntry propertyEntry)
        {
            var initialState = entityEntry.State;

            if (initialState == EntityState.Detached)
            {
                Assert.False(propertyEntry.IsModified);
                Assert.Throws<InvalidOperationException>(() => propertyEntry.IsModified = true).ValidateMessage(
                    "DbPropertyEntry_NotSupportedForDetached", "IsModified", propertyEntry.Name,
                    entityEntry.Entity.GetType().Name);
                return;
            }

            if (initialState == EntityState.Added || initialState == EntityState.Deleted)
            {
                Assert.False(propertyEntry.IsModified);
                Assert.Throws<InvalidOperationException>(() => propertyEntry.IsModified = true).ValidateMessage(
                    "ObjectStateEntry_SetModifiedStates");
                return;
            }

            propertyEntry.IsModified = true;
            Assert.True(propertyEntry.IsModified);
        }
        private void TestComplexOriginalValue(DbEntityEntry<Building> entityEntry,
                                              DbPropertyEntry<Building, SiteInfo> propertyEntry)
        {
            var initialState = entityEntry.State;

            if (initialState == EntityState.Added)
            {
                Assert.Throws<InvalidOperationException>(() => { var _ = propertyEntry.OriginalValue; }).ValidateMessage
                    ("DbPropertyValues_CannotGetValuesForState", "OriginalValues", "Added");
                Assert.Throws<InvalidOperationException>(() => propertyEntry.OriginalValue = new SiteInfo()).
                    ValidateMessage("DbPropertyValues_CannotGetValuesForState", "OriginalValues", "Added");
                return;
            }

            if (initialState == EntityState.Detached)
            {
                Assert.Throws<InvalidOperationException>(() => { var _ = propertyEntry.OriginalValue; }).ValidateMessage
                    ("DbPropertyEntry_NotSupportedForDetached", "OriginalValue", propertyEntry.Name,
                     typeof(Building).Name);
                Assert.Throws<InvalidOperationException>(() => propertyEntry.OriginalValue = new SiteInfo()).
                    ValidateMessage("DbPropertyEntry_NotSupportedForDetached", "OriginalValue", propertyEntry.Name,
                                    typeof(Building).Name);
                return;
            }

            Assert.Equal(initialState == EntityState.Modified, propertyEntry.IsModified);
            Assert.Equal("Clean", propertyEntry.OriginalValue.Environment);

            // Set to new object with the same values; should not get marked as modified because no values changing
            var sameInfo = CloneSiteInfo(propertyEntry.OriginalValue);
            propertyEntry.OriginalValue = sameInfo;
            Assert.Equal("Clean", propertyEntry.OriginalValue.Environment);
            Assert.Equal(initialState == EntityState.Modified, propertyEntry.IsModified);
            Assert.Equal(initialState, entityEntry.State);

            // Set to new value; prop marked as modified
            var newInfo = new SiteInfo { Zone = 2, Environment = "Contaminated" };

            propertyEntry.OriginalValue = newInfo;
            Assert.Equal("Contaminated", propertyEntry.OriginalValue.Environment);
            CheckPropertyIsModified(entityEntry, propertyEntry, initialState);

            // New value reflected in record
            if (initialState != EntityState.Added && initialState != EntityState.Detached)
            {
                var siteValues =
                    entityEntry.OriginalValues.GetValue<DbPropertyValues>("Address").GetValue<DbPropertyValues>(
                        "SiteInfo");

                Assert.Equal("Contaminated", siteValues["Environment"]);

                // Change record; new value reflected in entry
                siteValues["Environment"] = "Peachy";

                Assert.Equal("Peachy", propertyEntry.OriginalValue.Environment);
            }

            // Set to null
            Assert.Throws<InvalidOperationException>(() => propertyEntry.OriginalValue = null).ValidateMessage(
                "DbPropertyValues_ComplexObjectCannotBeNull", "SiteInfo", "Address");
        }
        private void TestComplexOriginalValue(DbEntityEntry<Building> entityEntry,
                                              DbPropertyEntry<Building, Address> propertyEntry)
        {
            var initialState = entityEntry.State;

            if (initialState == EntityState.Added)
            {
                Assert.Throws<InvalidOperationException>(() => { var _ = propertyEntry.OriginalValue; }).ValidateMessage
                    ("DbPropertyValues_CannotGetValuesForState", "OriginalValues", "Added");
                Assert.Throws<InvalidOperationException>(() => propertyEntry.OriginalValue = new Address()).
                    ValidateMessage("DbPropertyValues_CannotGetValuesForState", "OriginalValues", "Added");
                return;
            }

            if (initialState == EntityState.Detached)
            {
                Assert.Throws<InvalidOperationException>(() => { var _ = propertyEntry.OriginalValue; }).ValidateMessage
                    ("DbPropertyEntry_NotSupportedForDetached", "OriginalValue", propertyEntry.Name,
                     entityEntry.Entity.GetType().Name);
                Assert.Throws<InvalidOperationException>(() => propertyEntry.OriginalValue = new Address()).
                    ValidateMessage("DbPropertyEntry_NotSupportedForDetached", "OriginalValue", propertyEntry.Name,
                                    entityEntry.Entity.GetType().Name);
                return;
            }

            Assert.Equal(initialState == EntityState.Modified, propertyEntry.IsModified);
            Assert.Equal("Redmond", propertyEntry.OriginalValue.City);
            Assert.Equal("Clean", propertyEntry.OriginalValue.SiteInfo.Environment);

            // Set to new object with the same values; should not get marked as modified because no values changing
            var sameAddress = CloneAddress(propertyEntry.OriginalValue);
            propertyEntry.OriginalValue = sameAddress;
            Assert.Equal("Redmond", propertyEntry.OriginalValue.City);
            Assert.Equal("Clean", propertyEntry.OriginalValue.SiteInfo.Environment);
            Assert.Equal(initialState == EntityState.Modified, propertyEntry.IsModified);
            Assert.Equal(initialState, entityEntry.State);

            // Set to new value; prop marked as modified
            var newAddress = new Address
                             {
                                 Street = "300 Main St",
                                 City = "Ames",
                                 State = "IA",
                                 ZipCode = "50010",
                                 SiteInfo = new SiteInfo { Zone = 2, Environment = "Contaminated" }
                             };

            propertyEntry.OriginalValue = newAddress;
            Assert.Equal("Ames", propertyEntry.OriginalValue.City);
            Assert.Equal("Contaminated", propertyEntry.OriginalValue.SiteInfo.Environment);
            CheckPropertyIsModified(entityEntry, propertyEntry, initialState);

            // New value reflected in record
            if (initialState != EntityState.Added && initialState != EntityState.Detached)
            {
                var addressValues = (DbPropertyValues)entityEntry.OriginalValues["Address"];
                var siteValues = (DbPropertyValues)addressValues["SiteInfo"];

                Assert.Equal("Ames", addressValues["City"]);
                Assert.Equal("Contaminated", siteValues["Environment"]);

                // Change record; new value reflected in entry
                addressValues["City"] = "Cedar Falls";
                siteValues["Environment"] = "Peachy";

                Assert.Equal("Cedar Falls", propertyEntry.OriginalValue.City);
                Assert.Equal("Peachy", propertyEntry.OriginalValue.SiteInfo.Environment);
            }

            // Set to null
            Assert.Throws<InvalidOperationException>(() => propertyEntry.OriginalValue = null).ValidateMessage(
                "DbPropertyValues_ComplexObjectCannotBeNull", "Address", "Building");

            // Set to new value that has a nested null complex object
            // Should always throw, but Originally only throws if the entity is Added/Modified/Unchanged
            if (initialState != EntityState.Detached && initialState != EntityState.Deleted)
            {
                var addressWithNull = new Address
                                      {
                                          Street = "300 Main St",
                                          City = "Ames",
                                          State = "IA",
                                          ZipCode = "50010",
                                          SiteInfo = null
                                      };
                Assert.Throws<InvalidOperationException>(() => propertyEntry.OriginalValue = addressWithNull).
                    ValidateMessage("DbPropertyValues_ComplexObjectCannotBeNull", "SiteInfo", "Address");
            }
        }
 private void CheckPropertyIsModified(DbEntityEntry entityEntry, DbPropertyEntry propertyEntry,
                                      EntityState initialState)
 {
     if (initialState == EntityState.Modified || initialState == EntityState.Unchanged)
     {
         Assert.True(propertyEntry.IsModified);
         Assert.Equal(EntityState.Modified, entityEntry.State);
     }
     else
     {
         Assert.False(propertyEntry.IsModified);
         Assert.Equal(initialState, entityEntry.State);
     }
 }