Преобразование - SQL в 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
учебный класс:
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
учебный класс:
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
учебный класс:
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; }
}
2 ответа
dbContext.Items
.Where(x => x.Category.Name.Equals("Bread - Bakery"))
.Select(x => x.BrandID);
Я не уверен, почему вам нужно использовать ниже присоединиться. Кажется, что это не нужно (если только намеренно не объединить с брендами, чтобы удалить несоответствующие записи из предметов)
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
Вы только хотите сохранить эти Items
которые имеют категорию с Name
это равно Bread - Bakery
, Из оставшихся предметов вам нужны все их фирменные идентификаторы.
Требование было бы: "Дай мне BrandIds
из всех Items
которые имеют Category
с Name
что равно "Хлеб - Пекарня".
Если вы используете платформу сущностей, обычно проще, если вы используете virtual ICollection
вместо того, чтобы делать соединение самостоятельно. Платформа сущностей знает отношения между таблицами и будет составлять правильные соединения для нее.
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
Если вы действительно хотите и можете убедить своего руководителя проекта в том, что инфраструктуре сущностей нельзя доверять для правильного объединения, вы можете сделать это самостоятельно:
// 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
Вы понимаете, что ваш результат может иметь один и тот же BrandIds несколько раз, не так ли?
Если вы не хотите этого, начните с брендов:
var result = myDbContext.Brands
.Where(brand => brand.Items.Select(item => item.Category.Name)
.Where(name => name == "Bread - Bakery")
.Any())
.Select(brand => brand.brandId);
На словах: из коллекции брендов сохраните только те бренды, которые имеют хотя бы одну категорию с именем, равным "Хлеб - Пекарня". Из оставшихся брендов выберите BrandId.
** Замечание 2 **
Почему ваши списки один-ко-многим вместо ICollections? Вы уверены, что brand.Categories[4]
имеет правильное значение?
var result = myDbContext.Brands
.Where(brand => brand.Category[4].Name == "Bread - Bakeries");
Ваш компилятор не будет жаловаться, но вы получите ошибки во время выполнения.
Рассмотреть возможность использования virtual ICollection<...>
для ваших отношений один ко многим и многие ко многим. Таким образом, вы получите именно ту функциональность, которую ожидаете от таблицы базы данных, и ваш компилятор будет жаловаться, если вы попытаетесь использовать функциональность, которая не может быть преобразована в SQL