C# linq 省略的联接在使用 DefaultIfEmpty 时不起作用
本文关键字:DefaultIfEmpty 不起作用 linq | 更新日期: 2023-09-27 18:19:26
我是 c# 的新手,我有一个关于在 LINQ 中使用左连接的查询。
我有两个数据源 - 一个是类别集合,一个是产品集合。我想将这两个数据源连接在一起,以便我可以得到这样的结果:
Category Name (Fruit) - Product Name ( peach)- Source ( QLD,NSW).
请注意,我在产品集合中将源作为列表集合。
我这里有两个问题:
- 当我使用
DefaultIfEmpty
时,如果 nullSource
集合不存在,我无法设置正确的引用Souce
- 但是,如果产品名称不存在,我可以引用一个有意义的字符串说"不存在"。任何人都可以帮助展示如果左连接找不到产品的来源,如何放置空字符串? - 我找不到输出
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
,您需要使用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我认为这可能会对您有所帮助。