使用LINQ连接时丢失记录[重复]

bis0qfac  于 2023-09-28  发布在  其他
关注(0)|答案(1)|浏览(118)

此问题已在此处有答案

LEFT OUTER JOIN in LINQ(24回答)
上个月关门了。
使用C#和LINQ,我试图连接从搜索两个单独的表获得的列表。假设我有两个表,我正在为不同的项目提取不同的详细信息。

var _listOne = await _tableOne.Select( x => new
{
   Name = x.Name,
   ID = x.ID,
}).ToArrayAsync();

var _listTwo = await _tableTwo.Select( x => new
{
   Name = x.Name,
   Leader = x.Leader,
   Score = x.Score
}).ToArrayAsync();

请注意,这是一般化的信息,我有更多的字段,我抓取和许多过滤器,用于每个列表与特定条件有关。
当我尝试连接这两个列表时,我丢失了一些记录,我认为这是因为Map如何与.Join()一起工作。
所以,它的设置是这样的:

var _joinedLists = _listOne.Join(_listTwo,
                                 item => item.Name,
                                 details => details.Name,
                                 (item, details) => new
                                 {
                                   itemName = item.Name,
                                   ID = item.ID,
                                   leaderName = details.Leader,
                                   score = details.Score
                                 }).OrderByDescending(x => x.ID).ToArray();

假设某个名为“A”的记录位于_tableOne中,但“A”不在_tableTwo中,它没有在_joinedLists列表中加入“A”,它忽略了它。
主要目标是我想保留_listOne的所有记录,即使某些相关记录不在my _joinedLists的_listTwo中。
Join()应该是这样工作的,有没有办法绕过这个问题?我看过Union,但它似乎是这样做的,你必须有相同的字段(或者我认为返回类型)为每个字段和我的目的将不会工作。尝试在谷歌上搜索这个问题,但找不到任何其他联盟/Concat(但就像我说的,它不符合我的目的)。
谢谢.

ojsjcaue

ojsjcaue1#

你正在寻找的是一个左连接,得到所有的左源数据,并将其连接到其他源数据,无论它们是否匹配。如果没有连接链接(如您所说),RIGHT源数据字段将为NULL。
C#的左连接是方法 GroupJoin,我将向您展示两种方法。

第一个选项

第一个是按照你已经做过的,但这种方法的问题是,你从tableOne中获取所有数据到内存中,将这些数据存储在一个数组中,然后从tableTwo中获取所有数据并将其保存在内存中,第三个数组是这些数据的连接。正如你所看到的,我们有两个集合,它们可能有数千个数据,但不用于任何用途。所以我已经说过第二种选择是最好的。

var listOne = await _tableOne.Select( x => new
{
   Name = x.Name,
   ID = x.ID,
}).ToArrayAsync();

var listTwo = await _tableTwo.Select( x => new
{
   Name = x.Name,
   Leader = x.Leader,
   Score = x.Score
}).ToArrayAsync();

var joinedLists = listOne.GroupJoin(listTwo,
                                    item => item.Name,
                                    details => details.Name,
                                    (item, details) => new
                                    {
                                        ItemName = item.Name,
                                        item.ID,
                                        LeaderName = details.DefaultIfEmpty().FirstOrDefault()?.Leader,
                                        Score = details.DefaultIfEmpty().FirstOrDefault()?.Score
                                    })
                          .OrderByDescending(x => x.ID)
                          .ToArray();

第二个选项

正如我之前提到的,我认为第二种选择更好,因为我们只从数据库中获取一个已经完成连接的列表。因此,我们保存了内存和更少的处理。

var joinedLists = _tableOne.GroupJoin(_tableTwo,
                                      item => item.Name,
                                      details => details.Name,
                                      (item, details) => new
                                      {
                                          ItemName = item.Name,
                                          ID = item.ID,
                                          LeaderName = details.DefaultIfEmpty().FirstOrDefault()?.Leader,
                                          Score = details.DefaultIfEmpty().FirstOrDefault()?.Score
                                      })
                            .OrderByDescending(x => x.ID)
                            .ToArray();

顺便说一句,我改变了你的变量名。按照惯例(Microsoft),不要对方法范围变量使用下划线。
继续编码!

相关问题