2013-08-01 3 views
0

У меня есть два списка, возвращаемых через LINQ. Моя цель - вернуть все элементы из списка «defaults» минус то, что находится в списке «notDefaults».Исключая элементы, используя linq

В настоящее время я делаю это через два вложенных цикла и используя «RemoveAt». Может ли это быть сделано только с одной операцией LINQ? В принципе, мне нужно все в списке «defaults», если элемент не существует в таблице «AssetPayrollMarkupOverrides».

Я опасаюсь использования 'RemoveAt' с it appears to be slow.

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(); 

Я первоначально имел это таким образом, чтобы убедиться, что эти два списка совпадений:

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)); 

ответ

0
var notDefaultIds = notDefaults.Select(nd => nd.AssetID); 
var result = defaults.Where(def => !notDefaultIds.Any(id => id == def.AssetID); 

Если вы хотите, чтобы уменьшить DB туда и обратно, двигаться ToList() из notDefaults, defaults к result;

4

Вы можете использовать Except

var remaining = defaults.Except(notDefaults); 

Вы, возможно, потребуется, чтобы обеспечить ваше равенство компаратор на AssetMarkup является установите для сравнения объектов в режиме без ссылки.

Смотрите здесь http://msdn.microsoft.com/en-us/library/ms173147(v=vs.80).aspx

+0

Я прошу прощения за то, что не указал это в своем первоначальном посте, но я попытался использовать «Исключить», но, похоже, он не работал. Я также добавил те же OfficePercentage, MaintenancePercentage и Notes в каждый оператор linq, чтобы убедиться, что они точно совпадают, и «Except» по-прежнему не работает. return Json (defaults.Except (notDefaults) .OrderBy (x => x.AssetName) .ToDataSourceResult (запрос)); – Mithrilhall

+0

Вам нужно, чтобы у вас была перегружена Equals, которая правильно сравнивает объекты AssetMarkup. –

1

Что вы ищете, это complement двух комплектов. Except() метод Linq разработан, чтобы сделать это (вы можете использовать перегрузку, которая принимает 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()); 

Вы должны были бы объяснить нули в методах компаратора, но это только скелет пример.

Смежные вопросы