不包括使用linq的项目
本文关键字:项目 linq 不包括 | 更新日期: 2023-09-27 18:25:52
我有两个列表通过LINQ返回。我的目标是返回"defaults"列表中的所有项减去"notDefaults"列表的项。
我目前正在通过两个嵌套的for循环和使用RemoveAt来完成这项工作。这能只用一个LINQ语句完成吗?基本上,我需要"defaults"列表中的所有内容,除非该项存在于表"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();
我最初是这样做的,以确保两个列表匹配:
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));
您可以使用Except
var remaining = defaults.Except(notDefaults);
您可能需要确保AssetMarkup
上的相等比较器设置为以非基于引用的方式比较对象。
请参阅此处http://msdn.microsoft.com/en-us/library/ms173147(v=vs.80).aspx
您要查找的是这两个集合的补码。LinqException()方法就是为了做到这一点而设计的(您可以使用重载来获取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());
您需要考虑comparer方法中的null,但这只是一个骨架示例。
var notDefaultIds = notDefaults.Select(nd => nd.AssetID);
var result = defaults.Where(def => !notDefaultIds.Any(id => id == def.AssetID);
如果要减少数据库往返,请将ToList()
从notDefaults
、defaults
移动到result
;