我有一个类似于以下信息的DataSet。
我要做的是用尽可能多的信息填充对象。
所以我想从顶级数据集中获取UnitNum 65002,从单列表中获取其余部分。
我的代码:
foreach (DataRow row in dsUnits.Tables[0].Rows)
{
var unit = new Unit.Unit
{
UnitNum = row["UnitNumber"].NullSafeToString(),
CustCode = row["CustCode"].NullSafeToString(),
Year = row["Year"].NullSafeToString(),
Make = row["Make"].NullSafeToString(),
Model = row["Model"].NullSafeToString()
};
UnitsInvolvedInBreakdown.Add(unit);
}
foreach (DataRow row in dsUnits.Tables[1].Rows)
{
if (UnitsInvolvedInBreakdown.Where(x => x.UnitNum == row["UnitNumber"].ToString()).Count() == 0)
{
var unit = new Unit.Unit
{
UnitNum = row["UnitNumber"].ToString()
};
UnitsInvolvedInBreakdown.Add(unit);
}
}
这对我来说似乎效率很低,我尝试了以下代码并且没有结果,
var q = dsUnits.Tables[0].AsEnumerable().Except(dsUnits.Tables[1].AsEnumerable());
基本上我的问题是,有没有办法使用linq从表0中选择UnitNumbers,只有在表1中不存在
更好的解释。
单位编号将在表1中。它可能在表0中。
如果它在表0中,我想从那里获取信息..我有更多信息。
如果它不在表0中,我想从表1中获取信息,因为我必须得到我能得到的信息。但我不想重复。
答案 0 :(得分:1)
如果我理解了你的要求,这就是你要找的东西。它首先从表1中获取所有表,然后是表1中的所有表,但是在表2中通过Linq Left-Outer-Join:
var unitsFrom1 = dsUnits.Tables[0].AsEnumerable()
.Select(row => new Unit.Unit
{
UnitNum = row["UnitNumber"].NullSafeToString(),
CustCode = row["CustCode"].NullSafeToString(),
Year = row["Year"].NullSafeToString(),
Make = row["Make"].NullSafeToString(),
Model = row["Model"].NullSafeToString()
});
var unitsFrom2Notin1 =
from row in dsUnits.Tables[1].AsEnumerable()
join u1 in unitsFrom1
on row.Field<string>("UnitNumber") equals u1.UnitNum into outer
from outerJoin in outer.DefaultIfEmpty()
where outerJoin == null
select new Unit.Unit
{
UnitNum = row["UnitNumber"].NullSafeToString()
};
现在你可以连接两个:
IEnumerable<Unit.Unit> result = unitsFrom1.Concat(unitsFrom2Notin1);
这是一种更易于维护的不同方法,无论如何都应该有效。您可以实现自定义IEqualityComparer<Unit>
,您可以将其用于许多(基于集合)LINQ方法,例如Join
,Intersect
,Union
,GroupBy
。您也可以将它用于HashSet<Unit.Unit>
,在这种情况下我更喜欢它。以下是UnitComparer
:
public class UnitComparer : IEqualityComparer<Unit>
{
public bool Equals(Unit x, Unit y)
{
if (x == null && y == null) return true;
if (x == null || y == null) return false;
return x.UnitNum == y.UnitNum;
}
public int GetHashCode(Unit obj)
{
return obj == null || obj.UnitNum == null ? 0 : obj.UnitNum.GetHashCode();
}
}
这里是你需要的简单循环,从第一个开始,从第二个开始,不是第一个。请注意我使用的HashSet<T>
constructor:
var uniqueUnits = new HashSet<Unit.Unit>(new Unit.UnitComparer());
foreach (DataRow row in dsUnits.Tables[0].Rows)
{
Unit.Unit unit = new Unit.Unit
{
UnitNum = row["UnitNumber"].NullSafeToString(),
CustCode = row["CustCode"].NullSafeToString(),
Year = row["Year"].NullSafeToString(),
Make = row["Make"].NullSafeToString(),
Model = row["Model"].NullSafeToString()
};
uniqueUnits.Add(unit);
}
foreach (DataRow row in dsUnits.Tables[1].Rows)
{
Unit.Unit unit = new Unit.Unit
{
UnitNum = row["UnitNumber"].NullSafeToString()
};
uniqueUnits.Add(unit);
}
HashSet<T>.Add
如果无法添加,则会返回false
,因为它已经在集合中。
答案 1 :(得分:0)
我发现当我处于linq心态时,数据集往往会让我失望。我发现通过类构建实体更容易,然后使用linq查询实体。由于时间不够,我复制了一个MSDN示例。您可以根据需要对其进行修改。
var query =
from contact in contacts
from order in orders
where contact.ContactID == order.Contact.ContactID
&& order.TotalDue < totalDue
select new
{
ContactID = contact.ContactID,
LastName = contact.LastName,
FirstName = contact.FirstName,
OrderID = order.SalesOrderID,
Total = order.TotalDue
};
foreach (var smallOrder in query)
{
Console.WriteLine("Contact ID: {0} Name: {1}, {2} Order ID: {3} Total Due: ${4} ",
smallOrder.ContactID, smallOrder.LastName, smallOrder.FirstName,
smallOrder.OrderID, smallOrder.Total);
}
}