我是c#的新手,我有一个在LINQ中使用左连接的查询。
我有两个数据源 - 一个是类别集合,一个是产品集合。我想将这两个数据源连接在一起,这样我就可以得到这样的结果:
Category Name (Fruit) - Product Name ( peach)- Source ( QLD,NSW).
请注意我在产品系列中有Source as List集合。
我有两个问题:
DefaultIfEmpty
时,如果Source
不存在,我就无法设置对null 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
答案 0 :(得分:1)
我仍然不确定您要尝试实现的目标,但要使用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)
}
答案 1 :(得分:0)
使用此处发布的linq,左外连接有一个简单而整洁的扩展:http://www.codeproject.com/Tips/724333/Left-Outer-Join-extension-for-Entity-Framework 我想这可能会对你有帮助。