SQL to LINQ比较2个实体进行更改 - 创建审计跟踪

时间:2010-08-28 15:22:39

标签: .net linq-to-sql comparison

我正处于思考如何在代码中执行某些操作的假设阶段,所以我还没有具体的代码示例。但是,假设您有一个实体类型Person(具有名字,姓氏,DOB等属性)。当一个人去编辑一个人实体时,你可能只更新一个或两个字段(可能全部,但通常不是)。将此视为实施审计跟踪(虽然不是合法的,只是提供信息),即Tommy于8/28/2010将姓氏从Jones更改为Smith。

问题是,LINQ是否提供了一个界面来比较人员实体上从旧的,现有的更改到新提交的实体?

或者必须循环遍历旧实体和新实体属性并手动对每个实体进行比较吗?

伪:

For each p as property in person
   If oldEntity.p <> newEntity.p then
       auditEntry = new auditEntry(oldEntity.p, newEntity.p)
   end If
Next

或者,是否有其他/更好的方法(为部分类中的每个实体实现IComparable接口)可以做到这一点?

3 个答案:

答案 0 :(得分:1)

这不完全是你想要的,但我发布了一个解决方案的样本,我在几年前(LINQ之前的日子)创建了一个应用程序:

hint for audit log approach

它可能会有所帮助,让您以稍微不同的方式思考解决方案。

答案 1 :(得分:0)

答案 2 :(得分:0)

考虑以下例程:

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

        }
    }

您可以按如下方式比较两个对象:

CompareProperties<CustomerProduct>(product1, productFromDb)