преобразование - SQL в LINQ - PullRequest
       4

преобразование - SQL в LINQ

0 голосов
/ 03 января 2019

Как можно выполнить следующее, используя 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 ]

0 голосов
/ 03 января 2019

Хм, жаль, что вы не написали свои требования, теперь я должен догадаться, что они из вашего кода 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

0 голосов
/ 03 января 2019
dbContext.Items
  .Where(x => x.Category.Name.Equals("Bread - Bakery"))
  .Select(x => x.BrandID);

Я не уверен, почему вам нужно использовать ниже присоединиться.Кажется, что в этом нет необходимости (если только намеренно не объединить с брендами для удаления несоответствующих записей из элементов)

JOIN Brands AS d ON r.BrandID = d.BrandID
...