如何判断SubmitChanges()是否会实际更改LINQ to SQL中特定实体的任何内容

时间:2008-12-11 15:59:55

标签: vb.net linq-to-sql

我正在尝试确定是否对特定实体对象进行了任何更改。基本上,我想知道SubmitChanges()是否会实际改变任何东西。我希望能够在调用SubmitChanges()之后确定这一点,但这并不重要。

任何人都知道我会这样做吗?

4 个答案:

答案 0 :(得分:6)

查看DataContext上的GetChangeset函数。

答案 1 :(得分:2)

您可以使用父表直接访问附加实体实例的更改:

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(),因为更好的类型保真度,以及您可以轻松地自己检查更改的事实。

答案 2 :(得分:1)

你也可以尝试使用linq2sql的Helper类:

   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; }
    }


}

答案 3 :(得分:1)

这就是我提出的:

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
豫ICP备18024241号-1