如何创建正确的Lambda表达式来处理比较两个对象列表?

| 我有一个通过读取CSV文件创建的“ 0”。通过从数据库表读取,我得到了“ 1”。将lambda表达式设置为的正确方法是: 查找交集(“记录为更新”或“记录为无操作”) 在列表中找到新项(记录到INSERT) 在列表中找到不在列表中的项目(要删除的记录) 现在,我通过以下方式进行肌肉运动:
foreach (DTO.ImportData row in Helper.ImportTracker.ImportsValid)
{
    bool isInsert = false;
    bool isUpdate = false;
    Model.Auto auto = null;

    // Get auto(s) for this SKU + VIN + ClientID...
    var autos = _dbFeed.Autoes.Where(a => a.StockNumber == row.Stock && a.VIN == row.VIN && a.ClientID == _targetClientID && a.SourceClientID == _sourceClientID).ToList();
    if (autos.Count > 1)        // ERROR...
    {
        Helper.ImportTracker.ImportsInvalid.Add(row);
        continue;
    }
    else if (autos.Count == 1)  // UPDATE...
    {
        auto = autos[0];
        if (auto.GuaranteedSalePrice != row.GuaranteedSalePrice ||
            auto.ListPrice != row.ListPrice ||
            auto.Miles != row.Miles ||
            auto.Active != row.Active ||
            auto.MSRP != row.MSRP ||
            auto.InternetPrice != row.Internet_Price ||
            auto.InvoiceCost != row.Invoice ||
            auto.Make != row.Make ||
            auto.Model != row.Model ||
            auto.Year != row.Year 
            )
        {
            Helper.ImportTracker.Updates.Add(row);
            isUpdate = true;
        }
        else
        {
            isUpdate = false;
            auto = null;
        }
    }
    else                        // INSERT...
    {
        isInsert = true;
        auto = new Model.Auto();
        _dbFeed.Autoes.AddObject(auto);
        Helper.ImportTracker.Inserts.Add(row);
    }

    // Fill in the data...
    if (auto != null)
    {
        ...
    }
    // left out for readability - this section just maps the import 
    // data to the table row and saves to the DB...
}
上面的部分处理了我一开始列出的前两种情况。 我有点时间不知所措,以正确的方式将lambda组装在一起。 我意识到我可能必须将所有的
List<import>
转换为
List<table>
,这样我才能将一个苹果与另一个苹果进行比较,这不是问题。我还认为我需要按照以下方式编写自定义比较器:
class TableComparer : IEqualityComparer<table>
{
    public bool Equals(table x, table y)
    {
        if (Object.ReferenceEquals(x, y)) return true;

        if (Object.ReferenceEquals(x, null) ||
            Object.ReferenceEquals(y, null))
                return false;

            return x.SKU == y.SKU && x.VIN == y.VIN && x.ClientID == y.ClientID;
    }

    public int GetHashCode(table table)
    {
        if (Object.ReferenceEquals(table, null)) return 0;

        int hashSKU = SKU == null ? 0 : SKU.GetHashCode();
        int hashVIN = VIN == null ? 0 : VIN.GetHashCode();
        int hashClientID = ClientID.GetHashCode();

        return hashClientID ^ hashSKU ^ hashVIN;
    }
}
然后我可以做:
var UpdateAutos = autos.Intersect(new TableComparer(imports));
var InsertAutos = imports.Except(new TableComparer(autos));
var DeleteAutos = autos.Except(new TableComparer(imports));
现在我的头在旋转! ;) 我在正确的轨道上吗? 附加信息: 到目前为止,我已经有了新的代码:
private void HandleAutos()
{
    // convert to List<auto>...
    List<Model.Auto> imports = AutoConvert.Convert(Helper.ImportTracker.ImportsValid, _targetClientID, _sourceClientID, DateTime.UtcNow, _dbFeed);

    // get all DB records in List<auto>...
    List<Model.Auto> current = _dbFeed.Autoes.Where(a => a.ClientID == _targetClientID && a.Active == true).ToList();

    // isolate all Inserts, Updates and Deletes...
    var intersect = imports.Intersect(current, new AutoIsIn());         // should be all autos with matching VIN & SKU  //
    var updates = intersect.Intersect(current, new AutoHasChanged());   // should be a subset of changed resords        //
    var inserts = imports.Except(current, new AutoIsIn());              // should be all the imports not in the DB      //
    var deletes = current.Except(imports, new AutoIsIn());              // should be all the DB records not in imports  //

}
我的Comparer类如下所示:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RivWorks.FeedHandler.Library
{
    class AutoIsIn : IEqualityComparer<Model.Auto>
    {
        public bool Equals(Model.Auto x, Model.Auto y)
        {
            if (Object.ReferenceEquals(x, y)) return true;
            if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null)) return false;

            return x.StockNumber == y.StockNumber && x.VIN == y.VIN;
        }

        public int GetHashCode(Model.Auto auto)
        {
            if (Object.ReferenceEquals(auto, null)) return 0;

            int hashSKU = auto.StockNumber == null ? 0 : auto.StockNumber.GetHashCode();
            int hashVIN = auto.VIN == null ? 0 : auto.VIN.GetHashCode();

            return hashSKU ^ hashVIN;
        }
    }

    class AutoHasChanged : IEqualityComparer<Model.Auto>
    {
        public bool Equals(Model.Auto x, Model.Auto y)
        {
            if (Object.ReferenceEquals(x, y)) return true;
            if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null)) return false;

            return (x.GuaranteedSalePrice != y.GuaranteedSalePrice 
                 || x.ListPrice != y.ListPrice 
                 || x.Miles != y.Miles 
                 || x.MSRP != y.MSRP 
                 || x.InternetPrice != y.InternetPrice 
                 || x.InvoiceCost != y.InvoiceCost 
                 || x.Make != y.Make 
                 || x.Model != y.Model 
                 || x.Year != y.Year
                 );
        }

        public int GetHashCode(Model.Auto auto)
        {
            if (Object.ReferenceEquals(auto, null)) return 0;

            int hashMake = auto.Make == null ? 0 : auto.Make.GetHashCode();
            int hashModel = auto.Model == null ? 0 : auto.Model.GetHashCode();
            int hashYear = auto.Year.GetHashCode();

            int hashGSP = auto.GuaranteedSalePrice.GetHashCode();
            int hashLP = !auto.ListPrice.HasValue ? 0 : auto.ListPrice.GetHashCode();
            int hashMiles = !auto.Miles.HasValue ? 0 : auto.Miles.GetHashCode();
            int hashMSRP = !auto.MSRP.HasValue ? 0 : auto.MSRP.GetHashCode();
            int hashIP = !auto.InternetPrice.HasValue ? 0 : auto.InternetPrice.GetHashCode();
            int hashIC = !auto.InvoiceCost.HasValue ? 0 : auto.InvoiceCost.GetHashCode();

            return hashMake ^ hashModel ^ hashYear ^ hashGSP ^ hashLP ^ hashMiles ^ hashMSRP ^ hashIP ^ hashIC;
        }
    }
}
到目前为止有什么不对吗? -kb     
已邀请:
不是解决OP的问题,而是回应OP的评论...
Public Module ExpressionExtensions

    <System.Runtime.CompilerServices.Extension()> _
    Public Function Compose(Of T)(ByVal first As Expressions.Expression(Of T), ByVal second As Expressions.Expression(Of T), ByVal merge As Func(Of Expressions.Expression, Expressions.Expression, Expressions.Expression)) As Expressions.Expression(Of T)

        \' build parameter map (from parameters of second to parameters of first)
        Dim map = first.Parameters.[Select](Function(f, i) New With {f, .s = second.Parameters(i)}).ToDictionary(Function(p) p.s, Function(p) p.f)

        \' replace parameters in the second lambda expression with parameters from the first
        Dim secondBody = ParameterRebinder.ReplaceParameters(map, second.Body)

        \' apply composition of lambda expression bodies to parameters from the first expression 
        Return Expressions.Expression.Lambda(Of T)(merge(first.Body, secondBody), first.Parameters)
    End Function

    <System.Runtime.CompilerServices.Extension()> _
    Public Function [And](Of T)(ByVal first As Expressions.Expression(Of Func(Of T, Boolean)), ByVal second As Expressions.Expression(Of Func(Of T, Boolean))) As Expressions.Expression(Of Func(Of T, Boolean))
        Return first.Compose(second, AddressOf Expressions.Expression.And)
    End Function

    <System.Runtime.CompilerServices.Extension()> _
    Public Function [Or](Of T)(ByVal first As Expressions.Expression(Of Func(Of T, Boolean)), ByVal second As Expressions.Expression(Of Func(Of T, Boolean))) As Expressions.Expression(Of Func(Of T, Boolean))
        Return first.Compose(second, AddressOf Expressions.Expression.[Or])
    End Function

End Module
编辑:添加了缺少的ParameterRebinder
Public Class ParameterRebinder
    Inherits Expressions.ExpressionVisitor

    Private ReadOnly map As Dictionary(Of Expressions.ParameterExpression, Expressions.ParameterExpression)

    Public Sub New(ByVal map As Dictionary(Of Expressions.ParameterExpression, Expressions.ParameterExpression))
        Me.map = If(map, New Dictionary(Of Expressions.ParameterExpression, Expressions.ParameterExpression)())
    End Sub

    Public Shared Function ReplaceParameters(ByVal map As Dictionary(Of Expressions.ParameterExpression, Expressions.ParameterExpression), ByVal exp As Expressions.Expression) As Expressions.Expression
        Return New ParameterRebinder(map).Visit(exp)
    End Function

    Protected Overloads Overrides Function VisitParameter(ByVal p As Expressions.ParameterExpression) As Expressions.Expression
        Dim replacement As Expressions.ParameterExpression = Nothing
        If map.TryGetValue(p, replacement) Then
            p = replacement
        End If
        Return MyBase.VisitParameter(p)
    End Function
End Class
以上让您拥有...
Dim A as System.Func(Of MyType, Boolean) = Function(x) x.SomeField = SomeValue
Dim B as System.Func(Of MyType, Boolean) = A.Or(Function(x) x.SomeOtherField = SomeOtherValue)
Dim C as System.Func(Of MyType, Boolean) = A.And(Function(x) x.SomeOtherField = SomeOtherValue)
为了清楚起见,我已经明确键入了以上内容。不是必需的。 很抱歉加入VB-我已经掌握了代码,现在没有时间翻译     

要回复问题请先登录注册