繁体   English   中英

C#LINQ被遗忘的联接无法使用DefaultIfEmpty

[英]C# linq left out join does not work using DefaultIfEmpty

我是C#的新手,并且有一个查询要在LINQ中使用左联接。

我有两个数据源-一个是类别集合,一个是产品集合。 我想将这两个数据源连接在一起,以便获得如下结果:

Category Name (Fruit) - Product Name ( peach)- Source ( QLD,NSW).

请注意,我在产品集合中有“作为列表收集来源”。

我这里有两个问题:

  1. 当我使用DefaultIfEmpty ,如果Souce不存在,则无法为null Source集合设置正确的引用-但是,如果不存在有意义的字符串(例如“不存在”),则可以引用产品名称。 如果左联接找不到产品的来源,任何人都可以帮助显示如何放置空字符串?
  2. 我无法找到一种在最终结果中输出Category Name (如Fruit ,Vegetables ,尽管我可以在group join做到这一点,但对此有任何想法吗?

我在这里附加了我的代码。

class Product
{
    public string Name { get; set; }
    public int CategoryID { get; set; }
    public List<string> Source;
}

class Category
{
    public string Name { get; set; }
    public int ID { get; set; }
}
// Specify the first data source.
List<Category> categories = new List<Category>()
{ 
    new Category(){Name="Beverages", ID=001},
    new Category(){ Name="Condiments", ID=002},
    new Category(){ Name="Vegetables", ID=003},
    new Category() {  Name="Grains", ID=004},
    new Category() {  Name="Fruit", ID=005}            
};

// Specify the second data source.
List<Product> products = new List<Product>()
{
     new Product{Name="Cola",CategoryID=001,  Source = new List<string> {"NSW","VIC","QLD"} },  
     new Product{Name="Mustard", CategoryID=002 ,  Source = new List<string> {"NSW","VIC","SA"} },
     new Product{Name="Pickles", CategoryID=002 ,  Source = new List<string> {"NSW","VIC","NT"} },
     new Product{Name="Carrots", CategoryID=003 ,  Source = new List<string> {"NSW","VIC","TAS"} },
     new Product{Name="Bok Choy", CategoryID=003 ,  Source = new List<string> {"NSW","VIC","ACT"} },
     new Product{Name="Eggplant", CategoryID=003 ,  Source = new List<string> {"QLD","NSW"} },
     new Product{Name="Broccoli", CategoryID=003 ,  Source = new List<string> {"QLD,SA"} },
     new Product{Name="Peaches", CategoryID=005 ,  Source = new List<string> {"NSW","VIC","NZ"} },
     new Product{Name="Melons", CategoryID=005,  Source = new List<string> {"NSW","VIC"} },
};

以下代码不适用于LINQ中的left join联接:

void LeftOuterJoin()
{
   var leftOuterQuery =
       from category in categories
       join prod in products on category.ID equals prod.CategoryID into prodGroup          
       select prodGroup.DefaultIfEmpty(new Product()
       { Name = "Nothing!", CategoryID = category.ID})
       ;

    // Store the count of total items (for demonstration only). 
    int totalItems = 0;

    Console.WriteLine("Left Outer Join:");

    // A nested foreach statement  is required to access group items 
    foreach (var prodGrouping in leftOuterQuery)
    {
        Console.WriteLine("\nGroup count: {0}", prodGrouping.Count());

        // Intellisense does not show category name  if I use prodGrouping.Name 
         //and want to get categorhy name since left join produce hierarchy data 
         //why category name is not showing up - I am itinerate from 1st loop ??
        foreach (var item in prodGrouping)
        {
            totalItems++;
            Console.WriteLine("  {0,-10}{1}", item.Name, item.CategoryID);

            foreach (var s in item.Source)
            {
                Console.WriteLine("Souce state: {0}", s.ToString());
            }
        }
    }

    Console.WriteLine(System.Environment.NewLine);
}

嗨,Marcin,我更改了原来的代码,但是可以给我重复的记录,你知道为什么吗?

 void LeftOuterJoin()
    {
        // Create the query. 
        var leftOuterQuery =
           from category in categories
           join prod in products on category.ID equals prod.CategoryID into prodGroup
           from prodG in prodGroup.DefaultIfEmpty()       
            select new
            {
                Category = category.Name,
                //Products = products.OrderBy(x => x.Name)
                Products = from prod2 in prodGroup
                           orderby prod2.Name
                           select prod2
            };


        Console.WriteLine("Left Outer Join:");

        // A nested foreach statement  is required to access group items 
        foreach (var item in leftOuterQuery)
        {                 

             Console.WriteLine("  {0,-10}", item.Category);
             foreach ( var p in item.Products)
             {
                 Console.WriteLine("ProductName: {0}", p.Name);
                 foreach (var s in p.Source)
                 {
                     Console.WriteLine("SourceName: {0}", s.ToString());

                 }
             }                   


        }

    }

我想得到这样的结果:

  Group Beverages:1
  Cola      1
  Souce state: NSW
  Souce state: VIC
  Souce state: QLD

 Group : Condiments
  Mustard   2
   Souce state: NSW
   Souce state: VIC
   Souce state: SA
 Pickles   2
  Souce state: NSW
  Souce state: VIC
  Souce state: NT

但是我得到了这样的结果:

Beverages
 ProductName: Cola
 SourceName: NSW
 SourceName: VIC
 SourceName: QLD

Condiments
 ProductName: Mustard
 SourceName: NSW
 SourceName: VIC
 SourceName: SA    
 ProductName: Pickle
 SourceName: NSW
 SourceName: VIC
 SourceName: NT

Condiments
 ProductName: Mustard
 SourceName: NSW
 SourceName: VIC
 SourceName: SA
 ProductName: Pickle
 SourceName: NSW
 SourceName: VIC
 SourceName: NT

我仍然不确定您要实现的目标,但是要使用LINQ进行left outer join联接,您需要在from ....DefaultIfEmpty()使用join ... into from ....DefaultIfEmpty()

您正在使用select ....DefaultIfEmpty() ,这并不是您所需要的。

var leftOuterQuery =
    from category in categories
    join prod in products on category.ID equals prod.CategoryID into prodGroup
    from products in prodGroup.DefaultIfEmpty()       
    select new
    {
        Category = category.Name,
        Products = products.OrderBy(x => x.Name)
    }

有一个使用linq的左外部联接的简单简洁的扩展名,发布在这里: http : //www.codeproject.com/Tips/724333/Left-Outer-Join-extension-for-Entity-Framework我想这可能对您有所帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM