c# - 使用 LINQ 在两个表之间选择不同的值

标签 c# linq dataset

我有一个类似于以下信息的数据集。

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 中获取信息,因为我必须获取我能获取的信息。但我不想重复。

最佳答案

如果我了解您的要求,这就是您要找的。它首先从表一中获取所有内容,然后通过 Linq 左外连接获取所有不在表一中但在表二中的内容:

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如果因为它已经在集合中而无法添加。

关于c# - 使用 LINQ 在两个表之间选择不同的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29034929/

相关文章:

c# - 尝试从非常大的数据中从mysql中的多个相关表检索数据

dataset - 获取 Instagram 照片和主题标签的数据集

c# - 是否可以在不同的上下文中调用具有相同签名的两个函数? (属性操作)

c# - 如何对 DropDownList 进行排序

c# - S3 请求时间太偏斜

opencv - OpenCV SVM训练数据集

hadoop - HDFS、Hadoop 中的低延迟数据访问

c# - WPF:带 Canvas 的图像

c# - Linq 帮助使用 "Contains"

需要 c# LINQ Faster 解决方案。查询大型对象列表