Как определить, действительно ли SubmitChanges () изменит что-либо для конкретной сущности в LINQ to SQL - PullRequest
4 голосов
/ 11 декабря 2008

Я пытаюсь определить, были ли внесены какие-либо изменения в конкретный объект сущности. По сути, я хочу знать, действительно ли SubmitChanges () изменит что-либо. Я бы предпочел иметь возможность определить это после вызова SubmitChanges (), но это не имеет значения.

Кто-нибудь знает, как я это сделаю?

Ответы [ 4 ]

6 голосов
/ 11 декабря 2008

Посмотрите на функцию GetChangeset в вашем DataContext.

2 голосов
/ 12 декабря 2008

Вы можете напрямую получить доступ к изменениям для присоединенного экземпляра сущности, используя родительскую таблицу:

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
}

НО - конечно, вы должны сделать это до SubmitChanges (). Я использую этот подход вместо GetChangeSet () из-за лучшей точности типов и того факта, что вы можете легко проверить сами изменения.

1 голос
/ 29 августа 2015

также вы можете попробовать этот класс Helper для 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 голос
/ 12 декабря 2008

Вот что я придумал:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...