此外,您还可以尝试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; }
}
}