微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决如何创建正确的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,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,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-我已经掌握了代码,现在没有时间翻译     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。