我有一个List<imports>
,它是通过读取CSV文件创建的。通过从数据库表中读取,我有一个List<table>
。将lambda表达式设置为的正确方法是什么:
现在,我正在通过以下方式努力:
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...
}
以上部分处理我在开头列出的前两个案例。
我有一个时代的狄更斯以正确的方式将我的头围绕着将lambdas放在一起。
我意识到我可能需要将所有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
答案 0 :(得分:0)
不是解决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中道歉 - 我已经掌握了代码并且没有时间立即翻译