2015-03-13 87 views
2

我有一个如下所示的DataSet。使用LINQ在两个表之间选择不同的值

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.1

如果是在表0,我想要得到的信息,从there..i有更多的信息。

如果它不在表0中,我想从表1获取信息,因为我必须得到我所能得到的信息。但我不想重复。

+0

这是与实体框架? – 2015-03-13 14:38:41

+0

我想要... – DidIReallyWriteThat 2015-03-13 14:40:17

回答

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

现在你可以Concat的两个:

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,如果它不能被添加,因为它已经在集合。

+0

我喜欢它。我在想有一种方法可以使用Intersect功能。谢谢。我将运行一些单元测试来查看哪个更快。 – DidIReallyWriteThat 2015-03-13 14:59:57

+0

@CalvinSmith:我不明白'Intersect'在这里可以如何帮助。如果您在'Unit.Unit'中重写了'Equals' +'GetHashCode',则可以使用['Union'](https://msdn.microsoft.com/en-us/library/vstudio/bb341731%28v=vs。 100%29.aspx)。您也可以使用['Union'](https://msdn.microsoft.com/en-us/library/vstudio/bb358407(v = vs.100).aspx)的重载与自定义'IEqualityComparer '重载。 – 2015-03-13 15:03:13

+0

此外,它在concat中生成重复单元65002。我不认为只是在concat的末尾添加一个明显的可以修复它,但生病尝试下一个 – DidIReallyWriteThat 2015-03-13 15:07:42

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

}

+0

目前尚不清楚这是如何帮助从表1中全部获取,并且所有从表2中丢失这是核心问题。样本完全不相关,不是吗? – 2015-03-13 15:20:18

+0

这并没有真正回答这个问题。 – 2015-03-13 15:21:23

+0

我试图建议,而不是直接从查询数据集的转变。是样本不相关,但给出了一个查询实体的linq构造。它没有处理他的查询应该如何显示。我将研究这一点 – 2015-03-13 15:39:54