转换 - SQL 到 LINQ
conversion - SQL to LINQ
如何使用 LINQ
完成以下操作
SELECT r.BrandID
FROM dbo.Items AS r
JOIN Brands AS d ON r.BrandID = d.BrandID
WHERE CategoryID IN (SELECT CategoryID
FROM dbo.Categories
WHERE Name = 'Bread - Bakery')
Brand
class的代码:
public class Brand
{
public int BrandID { get; set; }
[DisplayName("Brand Name")]
public string Name { get; set; }
public virtual List<Category> Categories { get; set; }
public virtual List<Item> Items { get; set; }
}
Item
class的代码:
public class Item
{
[Key]
public int ItemID { get; set; }
public virtual Category Category { get; set; }
public virtual Brand Brand { get; set; }
public int CategoryID { get; set; }
public int BrandID { get; set; }
}
代码 Category
class:
public class Category
{
[Key]
public int CategoryID { get; set; }
[DisplayName("Category Name")]
public virtual string Name { get; set; }
public virtual List<Brand> Brands { get; set; }
public virtual List<Item> Items { get; set; }
}
dbContext.Items
.Where(x => x.Category.Name.Equals("Bread - Bakery"))
.Select(x => x.BrandID);
我不确定你为什么需要使用 below join。好像不需要(除非有意在品牌内部加入以从项目中删除不匹配的记录)
JOIN Brands AS d ON r.BrandID = d.BrandID
嗯,可惜你没有写你的要求,现在我得从你的SQL代码中猜出它们是什么。
所以你有一个包含 Brands
、Items
和 Categories
的数据库。每个Item
都有一个Category
,每个Category
可以被零个或多个Items
使用:一对多关系
每个 Item
都属于某个 Brand
,每个 Brand
可以有零个或多个项目:也是一个简单的一对多关系。
最后每个 Brand
都有零个或多个 Categories
,每个 Category
都有零个或多个 Brands
:多对多
现在您收集 Items
,您只想保留类别 Name
等于 Bread - Bakery
的那些 Items
。从其余项目中,您需要所有的 BrandIds。
要求是:“给我所有 Items
中 Category
和 Name
等于‘面包 - 面包店’的 BrandIds
。
如果您使用 entity framework,通常使用 virtual ICollection
比您自己进行连接更容易。 Entity framework 知道 table 之间的关系,并将为其编写适当的连接。
var result = myDbContext.Items // from the collection of Items
.Where(item => item.Category.Name == "Bread - Bakery") // keep only those with a Category
// that has a Name equal to ...
.Select(item.BrandId); // from the remaining items select the BrandId
如果你真的想要,并且你可以说服你的项目负责人 entity framework 不能相信你可以进行正确的连接,你可以自己进行连接:
// get the sequence of categories that I'm interested in:
var breadBakeryCategories = myDbContext.Categories
.Where(category => category.Name == "Bread - Bakery");
// join the items with these categories
// and select the BrandIds
var requestedBrandIds= myDbContext.Items
.Join(breadBakeryCategories,
item => item.CategoryId, // from every Item take the CategoryId,
category => category.CategoryId, // from every Category take the CategoryId
(item, category) => item.BrandId); // when they match, select the BrandId
TODO:考虑将其连接成一个丑陋的大 LINQ 语句。
备注1
您确实意识到您的结果可能多次具有相同的 BrandId,不是吗?
如果您不想这样,请从品牌开始:
var result = myDbContext.Brands
.Where(brand => brand.Items.Select(item => item.Category.Name)
.Where(name => name == "Bread - Bakery")
.Any())
.Select(brand => brand.brandId);
换句话说:从品牌集合中,只保留至少有一个类别名称等于 "Bread - Bakery" 的品牌。来自其余品牌 select BrandId。
** 备注 2 **
为什么你的一对多列表而不是 ICollections?您确定 brand.Categories[4]
具有正确的含义吗?
var result = myDbContext.Brands
.Where(brand => brand.Category[4].Name == "Bread - Bakeries");
您的编译器不会报错,但您会遇到运行时错误。
考虑将 virtual ICollection<...>
用于一对多和多对多关系。通过这种方式,您将完全拥有数据库 table 所期望的功能,如果您尝试使用无法转换为 SQL
的功能,您的编译器会报错
如何使用 LINQ
SELECT r.BrandID
FROM dbo.Items AS r
JOIN Brands AS d ON r.BrandID = d.BrandID
WHERE CategoryID IN (SELECT CategoryID
FROM dbo.Categories
WHERE Name = 'Bread - Bakery')
Brand
class的代码:
public class Brand
{
public int BrandID { get; set; }
[DisplayName("Brand Name")]
public string Name { get; set; }
public virtual List<Category> Categories { get; set; }
public virtual List<Item> Items { get; set; }
}
Item
class的代码:
public class Item
{
[Key]
public int ItemID { get; set; }
public virtual Category Category { get; set; }
public virtual Brand Brand { get; set; }
public int CategoryID { get; set; }
public int BrandID { get; set; }
}
代码 Category
class:
public class Category
{
[Key]
public int CategoryID { get; set; }
[DisplayName("Category Name")]
public virtual string Name { get; set; }
public virtual List<Brand> Brands { get; set; }
public virtual List<Item> Items { get; set; }
}
dbContext.Items
.Where(x => x.Category.Name.Equals("Bread - Bakery"))
.Select(x => x.BrandID);
我不确定你为什么需要使用 below join。好像不需要(除非有意在品牌内部加入以从项目中删除不匹配的记录)
JOIN Brands AS d ON r.BrandID = d.BrandID
嗯,可惜你没有写你的要求,现在我得从你的SQL代码中猜出它们是什么。
所以你有一个包含 Brands
、Items
和 Categories
的数据库。每个Item
都有一个Category
,每个Category
可以被零个或多个Items
使用:一对多关系
每个 Item
都属于某个 Brand
,每个 Brand
可以有零个或多个项目:也是一个简单的一对多关系。
最后每个 Brand
都有零个或多个 Categories
,每个 Category
都有零个或多个 Brands
:多对多
现在您收集 Items
,您只想保留类别 Name
等于 Bread - Bakery
的那些 Items
。从其余项目中,您需要所有的 BrandIds。
要求是:“给我所有 Items
中 Category
和 Name
等于‘面包 - 面包店’的 BrandIds
。
如果您使用 entity framework,通常使用 virtual ICollection
比您自己进行连接更容易。 Entity framework 知道 table 之间的关系,并将为其编写适当的连接。
var result = myDbContext.Items // from the collection of Items
.Where(item => item.Category.Name == "Bread - Bakery") // keep only those with a Category
// that has a Name equal to ...
.Select(item.BrandId); // from the remaining items select the BrandId
如果你真的想要,并且你可以说服你的项目负责人 entity framework 不能相信你可以进行正确的连接,你可以自己进行连接:
// get the sequence of categories that I'm interested in:
var breadBakeryCategories = myDbContext.Categories
.Where(category => category.Name == "Bread - Bakery");
// join the items with these categories
// and select the BrandIds
var requestedBrandIds= myDbContext.Items
.Join(breadBakeryCategories,
item => item.CategoryId, // from every Item take the CategoryId,
category => category.CategoryId, // from every Category take the CategoryId
(item, category) => item.BrandId); // when they match, select the BrandId
TODO:考虑将其连接成一个丑陋的大 LINQ 语句。
备注1
您确实意识到您的结果可能多次具有相同的 BrandId,不是吗?
如果您不想这样,请从品牌开始:
var result = myDbContext.Brands
.Where(brand => brand.Items.Select(item => item.Category.Name)
.Where(name => name == "Bread - Bakery")
.Any())
.Select(brand => brand.brandId);
换句话说:从品牌集合中,只保留至少有一个类别名称等于 "Bread - Bakery" 的品牌。来自其余品牌 select BrandId。
** 备注 2 **
为什么你的一对多列表而不是 ICollections?您确定 brand.Categories[4]
具有正确的含义吗?
var result = myDbContext.Brands
.Where(brand => brand.Category[4].Name == "Bread - Bakeries");
您的编译器不会报错,但您会遇到运行时错误。
考虑将 virtual ICollection<...>
用于一对多和多对多关系。通过这种方式,您将完全拥有数据库 table 所期望的功能,如果您尝试使用无法转换为 SQL