0

LINQ 経由で返される 2 つのリストがあります。私の目標は、「デフォルト」リストから「notDefaults」リストにあるものを除いたすべてのアイテムを返すことです。

現在、ネストされた 2 つの for ループと「RemoveAt」を使用してこれを行っています。これは 1 つの LINQ ステートメントだけで実行できますか? 基本的に、アイテムがテーブル「AssetPayrollMarkupOverrides」に存在しない限り、「デフォルト」リストのすべてが必要です。

「RemoveAt」は遅いように見えるので、使用することに不安を感じています。

var defaults = (from a in dbcontext.Assets
    join b in dbcontext.AssetAddresses on a.AssetID equals b.AssetID
    join c in dbcontext.Addresses on b.AddressID equals c.AddressID
    join d in dbcontext.StateLookups on c.StateID equals d.StateID
    where d.ShortName == state
    select new AssetMarkup()
    {
        AssetId = a.AssetID,
        AssetName = a.AssetName,
        Seg1_Code = a.Seg1_Code,
    }).ToList();


var notDefaults = (from a in dbcontext.Assets
    join b in dbcontext.AssetAddresses on a.AssetID equals b.AssetID
    join c in dbcontext.Addresses on b.AddressID equals c.AddressID
    join d in dbcontext.StateLookups on c.StateID equals d.StateID
    join e in dbcontext.AssetPayrollMarkupOverrides on a.AssetID equals e.AssetID
    where d.ShortName == state
    select new AssetMarkup()
    {
        AssetId = a.AssetID,
        AssetName = a.AssetName,
        Seg1_Code = a.Seg1_Code,
        ShortName = d.ShortName,
        OfficePercentage = e.OfficePercentage,
        MaintenancePercentage = e.MaintenancePercentage,
        Note = e.Note
    }).ToList();

私は元々、2 つのリストが一致することを確認するためにこの方法を使用していました。

var defaults = (from a in dbcontext.Assets
    join b in dbcontext.AssetAddresses on a.AssetID equals b.AssetID
    join c in dbcontext.Addresses on b.AddressID equals c.AddressID
    join d in dbcontext.StateLookups on c.StateID equals d.StateID
    where d.ShortName == state
    select new AssetMarkup()
    {
        AssetId = a.AssetID,
        AssetName = a.AssetName,
        Seg1_Code = a.Seg1_Code,
        ShortName = d.ShortName,
        OfficePercentage = dbcontext.PayrollMarkups.Where(x => x.StateID == c.StateID).Select(x => x.OfficePercentage).FirstOrDefault(),
        MaintenancePercentage = dbcontext.PayrollMarkups.Where(x => x.StateID == c.StateID).Select(x => x.MaintenancePercentage).FirstOrDefault(),
        Note = dbcontext.AssetPayrollMarkupOverrides.Where(x => x.AssetID == a.AssetID).Select(x => x.Note).FirstOrDefault()
    }).ToList();

var notDefaults = (from a in dbcontext.Assets
   join b in dbcontext.AssetAddresses on a.AssetID equals b.AssetID
   join c in dbcontext.Addresses on b.AddressID equals c.AddressID
   join d in dbcontext.StateLookups on c.StateID equals d.StateID
   join e in dbcontext.AssetPayrollMarkupOverrides on a.AssetID equals e.AssetID
   where d.ShortName == state
   select new AssetMarkup()
   {
       AssetId = a.AssetID,
       AssetName = a.AssetName,
       Seg1_Code = a.Seg1_Code,
       ShortName = d.ShortName,
       OfficePercentage = dbcontext.PayrollMarkups.Where(x => x.StateID == c.StateID).Select(x => x.OfficePercentage).FirstOrDefault(),
       MaintenancePercentage = dbcontext.PayrollMarkups.Where(x => x.StateID == c.StateID).Select(x => x.MaintenancePercentage).FirstOrDefault(),
       Note = dbcontext.AssetPayrollMarkupOverrides.Where(x => x.AssetID == a.AssetID).Select(x => x.Note).FirstOrDefault()
   }).ToList();

return Json(defaults.Except(notDefaults).OrderBy(x => x.AssetName).ToDataSourceResult(request));
4

3 に答える 3

1

あなたが探しているのは、2 つのセットを補完するものです。Linq のExcept()メソッドは、これを行うように設計されています (IEqualityComparer を受け取るオーバーロードを使用できます)。

public class AssetMarkupComparer : IEqualityComparer<AssetMarkup>
{
    public bool Equals(AssetMarkup am1, AssetMarkup am2)
    {
        return am1.AssetId == am2.AssetId;
    }

    public int GetHashCode(AssetMarkup obj)
    {
        return obj.AssetId.GetHashCode();
    }
}

var complement = defaults.Except(notDefaults, new AssetMarkupComparer());

比較メソッドで null を考慮する必要がありますが、これはスケルトンの例にすぎません。

于 2013-08-01T13:59:30.703 に答える
0
var notDefaultIds = notDefaults.Select(nd => nd.AssetID);
var result = defaults.Where(def => !notDefaultIds.Any(id => id == def.AssetID);

db のラウンドトリップを減らしたい場合は、ToList()からnotDefaultsに移動defaultsresultます。

于 2013-08-01T13:55:17.150 に答える