How to tell if SubmitChanges () will actually change anything for a specific object in LINQ to SQL

I am trying to determine if any changes have been made to any particular object of the object. Basically, I want to know if SubmitChanges () will actually change anything. I would prefer to define this after the SubmitChanges () method has been called, but it doesn't really matter.

Does anyone know how I would go about this?

+4


source to share


4 answers


This is what I came up with:



Public Function HasChanges(ByVal obj As Object) As Boolean
    Dim cs = GetChangeSet()
    If cs.Updates.Contains(obj) Or cs.Inserts.Contains(obj) Or cs.Deletes.Contains(obj) Then Return True
    Return False
End Function

      

+1


source


Take a look at the GetChangeset function in your DataContext.



+6


source


You can directly access changes for a connected entity object using the parent table:

var entityType = typeof(myEntity);
var table = dataContext.GetTable<entityType>();
var modifiedMembers = table.GetModifiedMembers(myEntity);

if (modifiedMembers.Any())
{
      ... changes were made
}
else
{
      ... no changes were made
}

      

BUT - you must do this before SubmitChanges () of course. I use this approach instead of GetChangeSet () because of the better font fidelity and the fact that you can easily test the changes yourself.

+2


source


also you can try this Helper class for linq2sql:

   public static class DataContextExtensions
{
    /// <summary>
    ///     Discard all pending changes of current DataContext.
    ///     All un-submitted changes, including insert/delete/modify will lost.
    /// </summary>
    /// <param name="context"></param>
    public static void DiscardPendingChanges(this DataContext context)
    {
        context.RefreshPendingChanges(RefreshMode.OverwriteCurrentValues);
        ChangeSet changeSet = context.GetChangeSet();
        if (changeSet != null)
        {
            //Undo inserts
            foreach (object objToInsert in changeSet.Inserts)
            {
                context.GetTable(objToInsert.GetType()).DeleteOnSubmit(objToInsert);
            }

            //Undo deletes
            foreach (object objToDelete in changeSet.Deletes)
            {
                context.GetTable(objToDelete.GetType()).InsertOnSubmit(objToDelete);
            }

            //Undo updates
            foreach (object objToUpdate in changeSet.Updates)
            {
                context.Refresh(RefreshMode.OverwriteCurrentValues, objToUpdate);
            }
        }
    }

    /// <summary>
    ///     Refreshes all pending Delete/Update entity objects of current DataContext according to the specified mode.
    ///     Nothing will do on Pending Insert entity objects.
    /// </summary>
    /// <param name="context"></param>
    /// <param name="refreshMode">A value that specifies how optimistic concurrency conflicts are handled.</param>
    public static void RefreshPendingChanges(this DataContext context, RefreshMode refreshMode)
    {
        ChangeSet changeSet = context.GetChangeSet();
        if (changeSet != null)
        {
            context.Refresh(refreshMode, changeSet.Deletes);
            context.Refresh(refreshMode, changeSet.Updates);
        }
    }
    /// <summary>
    /// Get list of items of specific type that have been changed in a context.including their original and new values
    /// </summary>
    /// <typeparam name="TItem"></typeparam>
    /// <param name="context"></param>
    /// <returns></returns>
    public static List<ChangedItems<TItem>> GetChangedItems<TItem>(DataContext context)
    {
        // create a dictionary of type TItem for return to caller
        List<ChangedItems<TItem>> changedItems = new List<ChangedItems<TItem>>();

        // use reflection to get changed items from data context
        object services = context.GetType().BaseType.GetField("services",
            BindingFlags.NonPublic |
            BindingFlags.Instance |
            BindingFlags.GetField).GetValue(context);

        object tracker = services.GetType().GetField("tracker",
            BindingFlags.NonPublic |
            BindingFlags.Instance |
            BindingFlags.GetField).GetValue(services);
        System.Collections.IDictionary trackerItems =
            (System.Collections.IDictionary)tracker.GetType().GetField("items",
                BindingFlags.NonPublic |
                BindingFlags.Instance |
                BindingFlags.GetField).GetValue(tracker);

        // iterate through each item in context, adding
        // only those that are of type TItem to the changedItems dictionary
        foreach (System.Collections.DictionaryEntry entry in trackerItems)
        {
            object original = entry.Value.GetType().GetField("original",
                BindingFlags.NonPublic |
                BindingFlags.Instance |
                BindingFlags.GetField).GetValue(entry.Value);

            if (entry.Key is TItem && original is TItem)
            {
                changedItems.Add(
                    new ChangedItems<TItem>((TItem)entry.Key, (TItem)original)
                    );
            }
        }
        return changedItems;
    }

    /// <summary>
    /// Returns a list consist a pair if original-current values of each property for the given type.
    /// First KeyValue is current and second one is original.
    /// </summary>/// <typeparam name="T"></typeparam>
    /// <param name="context"></param>
    /// <returns></returns>
    public static List<Dictionary<string, object>> GetObjectDiff<T>(this DataContext context)
    {
        List<Dictionary<string, object>> diff = new List<Dictionary<string, object>>();

        try
        {
            Debuging.Info("Try to GetObjectDiff");
            var changes = DataContextExtensions.GetChangedItems<T>(context);

            foreach (ChangedItems<T> changedItem in changes)
            {
                PropertyInfo[] props = typeof(T).GetProperties();

                var dictCurrent = new Dictionary<string, object>();

                foreach (PropertyInfo prp in props)
                {
                    object value = prp.GetValue(changedItem.Current, new object[] { });
                    dictCurrent.Add(prp.Name, value);
                }

                var dictOrigin = new Dictionary<string, object>();

                foreach (PropertyInfo prp in props)
                {
                    object value = prp.GetValue(changedItem.Original, new object[] { });
                    dictOrigin.Add(prp.Name, value);
                }

                foreach (var item in dictCurrent)
                {
                    var paired = dictOrigin.SingleOrDefault(a => a.Key == item.Key);
                    if (paired.Value != item.Value)
                    {
                        var first = new Dictionary<string, object>();
                        first.Add(item.Key,item.Value);
                        diff.Add(first);

                        var second = new Dictionary<string, object>();
                        second.Add(paired.Key, paired.Value);
                        diff.Add(second);
                    }
                }
            }
        }
        catch (Exception ex)
        {
            Debuging.Error(ex, "DataContextExtensions.GetObjectDiff");
        }
        return diff;
    }

    /// <summary>
    /// Detect if there is any changed object in the context or not.
    /// </summary>
    public static bool HasChanges(this DataContext context)
    {
        ChangeSet changeSet = context.GetChangeSet();

        if (changeSet != null)
        {
            return changeSet.Inserts.Any() || changeSet.Deletes.Any() || changeSet.Updates.Any();
        }

        return false;
    }

    public class ChangedItems<T>
    {
        public ChangedItems(T current, T original)
        {
            this.Current = current;
            this.Original = original;
        }

        public T Current { get; set; }
        public T Original { get; set; }
    }


}

      

+1


source







All Articles