如何解决如何创建正确的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 举报,一经查实,本站将立刻删除。