I am in the hypothetical phase of thinking of how to do something in code, so I have no concrete code examples yet. But, let's assume you have an entity type Person (with attributes such as first name, last name, DOB, etc.). When one goes to edit a person entity, you may only update one or two fields (possibly all, but usually not). Think of this as implementing an audit trail (albeit not a legal one, just informational), i.e. Tommy changed last name from Jones to Smith on 8/28/2010.
The question is, does LINQ provide an interface to compare what was changed on the person entity from the old, existing one to the newly submitted one?
Or must one loop through the old entity and the new entities properties and do a comparison on each one manually?
Pseudo:
For each p as property in person
If oldEntity.p <> newEntity.p then
auditEntry = new auditEntry(oldEntity.p, newEntity.p)
end If
Next
Or, is ther开发者_如何学运维e another/better way (implement an IComparable interface for each entity in a partial class) that can do this?
This isn't exactly what your looking for but I posted a sample of a solution I used for an application I created a few years back (pre LINQ days) on this thread:
hint for audit log approach
It might be of help and get you thinking about the solution in a slightly different way.
DataContext.GetChangeSet and Table.GetOriginalEntityState is what you're looking for -
http://msdn.microsoft.com/en-us/library/system.data.linq.datacontext.getchangeset.aspx
http://msdn.microsoft.com/en-us/library/bb548700.aspx
Given the following routines:
public static void CompareProperties<T>(object source, object target)
{
Type type = typeof(T);
CompareProperties(type, source, target);
if (type.IsInterface)
{
Type[] baseTypes = type.GetInterfaces();
foreach (var baseType in baseTypes)
{
CompareProperties(baseType, source, target);
}
}
else
{
type = type.BaseType;
while (type != null)
{
CompareProperties(type, source, target);
type = type.BaseType;
}
}
}
private static void CompareProperties(Type type, object source, object target)
{
PropertyInfo[] props = type.GetProperties(
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
PropertyInfo[] props1 = source.GetType().GetProperties(
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
PropertyInfo[] props2 = target.GetType().GetProperties(
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo pi in props)
{
if (!pi.CanRead || !pi.CanWrite)
continue;
var name = pi.Name;
var pi1 = props1.Where(x => x.Name == name).FirstOrDefault();
var pi2 = props2.Where(x => x.Name == name).FirstOrDefault();
if(pi1 == null || pi2 == null)
continue;
var expected = pi1.GetValue(source, null);
var actual = pi2.GetValue(target, null);
if(pi.PropertyType == typeof(int?))
{
expected = expected ?? 0;
actual = actual ?? 0;
}
if (pi2.PropertyType.IsEnum && !pi.PropertyType.IsEnum)
{
continue;
expected = (int)expected;
actual = (int)actual;
}
Assert.AreEqual(expected, actual, "The property '" + pi.Name + "' was not saved for the " + source.GetType().Name);
}
}
You can compare two objects as follows:
CompareProperties<CustomerProduct>(product1, productFromDb)
精彩评论