views:

59

answers:

2

Hi all,

I have the following extension method and i'm not sure why each entrys state is being changed to Unchanged after i call entry.AcceptChanges() on one entry.

    public static void SaveWithLogging(this ObjectContext context)
    {
        IEnumerable<ObjectStateEntry> entries = context.ObjectStateManager.GetObjectStateEntries(EntityState.Modified | EntityState.Added | EntityState.Deleted);
        foreach (var entry in entries)
            CreateTransactionLog(context, entry);
    }


    private static void CreateTransactionLog(ObjectContext context, ObjectStateEntry entry)
    {
        using (TransactionScope transaction = new TransactionScope())
        {

            string operationType = entry.State.ToString();

            context.SaveChanges(SaveOptions.DetectChangesBeforeSave);
            if (entry.State == EntityState.Added) entry.AcceptChanges();

            var columnNames = (from p in entry.EntitySet.ElementType.Members
                               select p.Name)
                               .ToList();

            Log log = new Log();
            log.CreateDate= DateTime.Now;
            log.UserName = "Test";
            log.Operation = operationType;
            context.AddObject("Logs", log);

            foreach (var columnName in columnNames)
            {
                string oldValue = entry.State == EntityState.Added ? string.Empty : entry.OriginalValues[columnName].ToString();
                string newValue = entry.CurrentValues[columnName].ToString();
                if (oldValue.CompareTo(newValue) != 0)
                {
                    // Create Log Details
                    LogDetail logDetails = LogDetail();
                    logDetails.LogId = log.LogId;
                    logDetails.TableName = entry.EntitySet.Name.ToString();
                    logDetails.Field = columnName.ToString();
                    logDetails.Before = oldValue;
                    logDetails.After = newValue;
                    logDetails.PKValue = entry.CurrentValues[0].ToString();
                    context.AddObject("LogDetails", logDetails);
                }
            }
            context.SaveChanges();
            transaction.Complete();
        }
    }

Am i doing something incorrectly?

Thanks

A: 

The AcceptChanges method does this by design.
What behavior do you expect?

Devart
Shouldn't entry.AcceptChanges() only accept changes for that particular entity and not the entire context?
zSysop
+1  A: 

Yes, that is correct. ObjectStateEntry.AcceptChanges is similar to ObjectContext.AcceptAllChanges, except that it will impact only the specific entity.

The important point is that by default, the SaveChanges method calls AcceptAllChanges method after it has performed the database modifications. Then AcceptAllChanges pushes the current values of every attached entity into the original values and then changes their EntityState to Unchanged.

As you can see, your issue coming from the fact that context.SaveChanges() is called on the first iteration of your foreach, therefore a AcceptAllChanges() is invoked by SaveChanges() and that make everyone to go into Unchanged state.

Morteza Manavi
Thanks Morteza!
zSysop
You're welcome :)
Morteza Manavi