У меня есть List<imports>
, который создается путем чтения файла CSV. У меня есть List<table>
, читая из таблицы базы данных. Как правильно настроить лямбда-выражения на:
- Найти пересечение (Записи для ОБНОВЛЕНИЯ или Записи без ДЕЙСТВИЯ)
- Найти новые предметы в списке (Записи в 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...
}
В приведенном выше разделе рассматриваются первые 2 случая, которые я перечислил в начале.
У меня есть время, когда я оборачиваюсь вокруг правильного способа собрать лямбды для этого.
Я понимаю, что мне, возможно, придется конвертировать все свои 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