Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / ASP.NET [игнор отключен] [закрыт для гостей] / Как получить данные много-ко-многим, при отключенном lazy loading - EF6 / 9 сообщений из 9, страница 1 из 1
15.05.2016, 12:28
    #39235954
unsafe
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить данные много-ко-многим, при отключенном lazy loading - EF6
Стажируюсь. Lazy loading, или на русском отложенное исполнение, нам сказали отключить. Обосновили это тем, что хоть это и удобно, сзади создаются дополнительные заявки, что сказывается на производительности. По скольку lazy loading отключен, надобность в ключевом слове virtual отпадает, мы его удаляем, а так же отключаем proxy.
DbContext:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
    class MyCommerceContext : DbContext
    {
        public MyCommerceContext() : base("ModelClassesDatabase.Properties.Settings.DBConnection")
        {
            Database.Log = s => System.Diagnostics.Debug.WriteLine(s); // print sql query in output
            Configuration.LazyLoadingEnabled = false; // disable lazy loading
            Configuration.ProxyCreationEnabled = false; // disable proxy creation
        }

        public DbSet<Category> Categories { get; set; }
        public DbSet<Product> Products { get; set; }
        public DbSet<Order> Orders { get; set; }
        //public DbSet<ProductOrder> ProductsOrders { get; set; }
        
    }


Встаёт вопрос, как теперь получить данные из БД?
Хотя схема БД выглядит следующем образом:

В c# её можно представить лишь тремя классами. И джоинвать не получиться.
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
    
    [Table("Categories")]
    public class Category
    {
        public int ID { get; set; }
        public string Name { get; set; }

        public ICollection<Product> Product { get; set; }

        public Category()
        {
            Product = new HashSet<Product>();
        }
    }

    [Table("Orders")]
    public class Order
    {
        public int ID { get; set; }
        public string ShipAddress { get; set; }

        public ICollection<Product> Products { get; set; }

        public Order()
        {
            Products = new List<Product>();
        }
    }

    [Table("Products")]
    public class Product
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
        public int? CategoryID { get; set; }

        public Category Category { get; set; }
        public ICollection<Order> Orders { get; set; }

        public Product()
        {
            Orders = new List<Order>();
        }
    }

...
Рейтинг: 0 / 0
15.05.2016, 12:38
    #39235959
skyANA
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить данные много-ко-многим, при отключенном lazy loading - EF6
unsafe, что получить-то надо? С точки зрения пользователя.
...
Рейтинг: 0 / 0
15.05.2016, 12:53
    #39235963
unsafe
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить данные много-ко-многим, при отключенном lazy loading - EF6
skyANA, Привет. Нужно получить продукты со списком заказов к каждому продукту.
...
Рейтинг: 0 / 0
15.05.2016, 18:45
    #39236077
handmadeFromRu
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить данные много-ко-многим, при отключенном lazy loading - EF6
unsafeВ c# её можно представить лишь тремя классами
ну изза того что ты прокинул в ProductsOrders ключ первичный ID то 4 класса, если в 3 класса то надо убрать ID и дописать что то типо

Код: c#
1.
2.
3.
4.
 modelBuilder.Entity<Product>()
                .HasMany(e => e.Order)
                .WithMany(e => e.Product)
                .Map(m => m.ToTable("ProductOrder").MapLeftKey("ProductId").MapRightKey("OrderId"));



и что мешает сделать то вот так:
Код: c#
1.
var model = db.Products. select (x => new { x, orders =  x.Orders}).toList();


EF6 сгенерит запрос примерно такой
Код: sql
1.
 select from product inner join productorder inner join orders


а потом уже он сам сгруппирует заказы в коллекцию, если ты бы писал на голом sql тож самое делал бы, просто обходил коллекцию и группировал по товару, вариантов других нет если тащить 1 запросом.

п.с. ваще не вижу смысла отключения Lazy loading, просто dto на конкретную форму и проблем нет с Lazy loading вообще, хотя может ради соблазна, но он(lazy) полезен все таки порой.
...
Рейтинг: 0 / 0
15.05.2016, 20:35
    #39236130
unsafe
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить данные много-ко-многим, при отключенном lazy loading - EF6
handmadeFromRuunsafeВ c# её можно представить лишь тремя классами
ну изза того что ты прокинул в ProductsOrders ключ первичный ID то 4 класса, если в 3 класса то надо убрать ID и дописать что то типо

Я имел ввиду что можно и тремя классами. Вообще честно говоря мне это кажется немного странным. Вы как более опытнай разработчик подскажите, как поступить?
handmadeFromRu
Код: c#
1.
2.
3.
4.
 modelBuilder.Entity<Product>()
                .HasMany(e => e.Order)
                .WithMany(e => e.Product)
                .Map(m => m.ToTable("ProductOrder").MapLeftKey("ProductId").MapRightKey("OrderId"));



Спасибо, буду знать куда рыть.
handmadeFromRu
Код: c#
1.
var model = db.Products. select (x => new { x, orders =  x.Orders}).toList();


EF6 сгенерит запрос примерно такой
Код: sql
1.
 select from product inner join productorder inner join orders


а потом уже он сам сгруппирует заказы в коллекцию, если ты бы писал на голом sql тож самое делал бы, просто обходил коллекцию и группировал по товару, вариантов других нет если тащить 1 запросом.

п.с. ваще не вижу смысла отключения Lazy loading, просто dto на конкретную форму и проблем нет с Lazy loading вообще, хотя может ради соблазна, но он(lazy) полезен все таки порой.
В этом ведь и весь смысл. Мы отключаем lazy loading, так как он сзади создает несколько заявок, да ещё и прокси генерит, и тащим всё одной заявкой.
...
Рейтинг: 0 / 0
15.05.2016, 23:40
    #39236193
handmadeFromRu
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить данные много-ко-многим, при отключенном lazy loading - EF6
unsafeЯ имел ввиду что можно и тремя классами. Вообще честно говоря мне это кажется немного странным. Вы как более опытнай разработчик подскажите, как поступить?

ну тут как бы если по феншую то выкидываешь id из ProductsOrders , потому что ключ лишний, у тебя итак естественый ключ по 2 полям. А так бывает приходится денормализировать таблицы ради профита, тут тебе решать надо самому. Ну и добавление через 4 таблицу как то понятнее выглядит по началу.

unsafeВ этом ведь и весь смысл. Мы отключаем lazy loading, так как он сзади создает несколько заявок, да ещё и прокси генерит, и тащим всё одной заявкой.

дело не в lazy loading, а как использовать инструмент. Я ж написал тебе как на линку будет запрос выглядить, 1 ручкой подтянет все, и ничего отключать не надо.

п.с. хз я вот юзаю lazy loading внутри 1 контекста, если уж тормозит то да я делаю dto-ку. если там массовое сохранние то ваще sqlbulk привет)
...
Рейтинг: 0 / 0
16.05.2016, 11:33
    #39236370
unsafe
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить данные много-ко-многим, при отключенном lazy loading - EF6
handmadeFromRu, Будет ещё пара вопросов. К примеру пускаю цикл
Код: c#
1.
2.
3.
4.
5.
foreach (var category in db.Categories)
{
    foreach (var product in category.Products)
        Console.WriteLine($"Category name: {category.Name}, product price: {product.Price}, product name: {product.Name}");
}


1) Причем если, вместо db.Categories написать db.Categories.ToList() то список категорий будет больше. Да же не знаю в чём причина такого вывода, единственно что в голову подкрадывается, так это что в таком случае EF использует LEFT JOIN. Но заявки вроде бы идентичные.

2) У меня в классе Category создан список с продуктами. Подгрузить данные в этом в же цикле через category.Products не получается. Правда если перед циклом прописать db.Products.ToList() то всё успешно подгружается. Поняв что эту связь надо то же настроить вручную, руководствуясь мануалом написал следующее:
Код: c#
1.
2.
3.
4.
modelBuilder.Entity<Category>()
    .HasMany(c => c.Products)
    .WithRequired(p => p.Category)
    .HasForeignKey(p => p.CategoryID);


Но это не помогло.
3) Что касается переопределения функции OnModelCreating, при отключении lazy loading, надо ли все связи настраивать вручную с помощью Fluent API.
...
Рейтинг: 0 / 0
17.05.2016, 19:10
    #39237724
handmadeFromRu
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить данные много-ко-многим, при отключенном lazy loading - EF6
unsafehandmadeFromRu, Будет ещё пара вопросов. К примеру пускаю цикл
Код: c#
1.
2.
3.
4.
5.
foreach (var category in db.Categories)
{
    foreach (var product in category.Products)
        Console.WriteLine($"Category name: {category.Name}, product price: {product.Price}, product name: {product.Name}");
}



ну а чего тебе не сгенерить дто тут ? зачем сам обходить с подзапросом?
Код: c#
1.
2.
3.
var temp = db.Categories.select (x=>  new { x, prods = x. Products}).tolist();
or
var temp =db.Product .Select( x => new { x.price, x.name , category = x.category.name }).tolist()



[quot unsafe]
Код: c#
1.
2.
3.
4.
modelBuilder.Entity<Category>()
    .HasMany(c => c.Products)
    .WithRequired(p => p.Category)
    .HasForeignKey(p => p.CategoryID);


ну вроде с виду правильно. но если ты используешь нотацию аля categoryId => Category но для 1 :n ef сам разрулит.
unsafe3) Что касается переопределения функции OnModelCreating, при отключении lazy loading, надо ли все связи настраивать вручную с помощью Fluent API.
руками надо когда у тебя ключи и сущности не в нотации вы указанной выше, или сложные варианты n:n и какие то особые случаи.

п.с. можно еще атрибутами эт заменить.
...
Рейтинг: 0 / 0
17.05.2016, 21:15
    #39237764
unsafe
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить данные много-ко-многим, при отключенном lazy loading - EF6
handmadeFromRu, Я вроде бы совсем разобрался. Я пускал цикл именно таким образом в надежде получать такой же простой доступ к категориям через продукты, как если бы был включен lazy loading. Спасибо Вам.
...
Рейтинг: 0 / 0
Форумы / ASP.NET [игнор отключен] [закрыт для гостей] / Как получить данные много-ко-многим, при отключенном lazy loading - EF6 / 9 сообщений из 9, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]