Как избежать извлечения ненужных данных, которые занимают дополнительное время - PullRequest
0 голосов
/ 07 января 2019

У меня есть эти три модели A, B, C.

Предположим, эти классы выглядят так:

Public class A 
{
    public int Id {get;set;}
    public string Name {get;set;}
    public ICollection<B> bc {get;set;} 
    public ICollection<C> cc {get;set} 
}

Public class B 
{
    public int Id {get;set;}
    public string Name {get;set;}
}

Public class C  
{
    public int Id {get;set;}
    public string Name {get;set;}
}

Предположим, мне нужны все данные от A, кроме cc или bc.

Проблема в том, что всякий раз, когда я вызываю метод getall, он возвращает все связанное, на самом деле он намного сложнее в моем коде, поэтому в B и C есть также коллекции, которые приносят почти все, и для их выполнения требуется много времени, это как петля.

До сих пор я пытался использовать select, но все еще переходил к модели и извлекал все поля.

Любая помощь Пожалуйста, и спасибо.

Ответы [ 2 ]

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

Я подозреваю, что вы, возможно, неправильно используете .Select, потому что это именно то, для чего он предназначен.

Чтобы получить соответствующие данные A, без B или C:

var aDetails = context.As.Select(a => new { a.Id, a.Name }).ToList();

Обратите внимание, что при этом возвращается анонимный тип, содержащий только те поля, которые вы хотите, в данном случае идентификатор и имя из записей A. Теперь, если вы хотите вернуть эти данные для использования в представлении и т. Д., Вы можете определить класс модели представления с именем AViewModel, например, с этим идентификатором и именем:

var viewModels = context.As.Select(a => new AViewModel{ Id = a.Id, Name = a.Name }).ToList();

Часто люди попадают в ловушку, пытаясь отправить объекты в представление. Это плохой, плохой шаблон, который слишком часто застекляется ради того, чтобы избежать определения другого класса POCO, который очень похож на сущность. Однако есть две действительно веские причины, по которым вам следует избегать этого: безопасность информации и производительность. (Обрисовано в общих чертах здесь ) Если вы делаете что-то вроде:

var results = context.As.ToList();

или даже

var results = context.As.Select(a => a).ToList();

При включенном LazyLoading (EF6) Это загрузит только ваши записи A без B или C. Однако, если вы попытаетесь передать эти объекты обратно вашему клиенту, сериализатор будет выполнять итерацию по каждому свойству, отключая ленивую загрузку в коллекциях B и C, загружая каждый набор для каждой отдельной записи A. При возврате коллекции A это будет намного, гораздо хуже, чем если бы вы с нетерпением загрузили B и C в своем запросе, потому что, если вы возвращаете записи 5x A, ленивые вызовы загрузки составят:

ВЫБРАТЬ ИЗ B, ГДЕ AId = 1, ВЫБРАТЬ ИЗ B, ГДЕ AId = 2, ...

ВЫБРАТЬ ИЗ C, ГДЕ AId = 1, ВЫБРАТЬ ИЗ C, ГДЕ AId = 2, ...

10x дополнительных операторов SQL вместо включения всех связанных строк B и C в один начальный (больший) оператор SQL. Вы можете избежать этой ловушки производительности, отключив ленивую загрузку EF (отключив прокси), но тогда у вас останутся пустые коллекции, которые не отражают ваше реальное состояние данных. (ИМО объект должен всегда полностью представлять свое состояние данных, не догадываясь, просто ли отсутствующие данные не были загружены, или объект фактически не имеет связанных данных.)

Чтобы узнать, как Select может улучшить производительность; Допустим, у вас есть набор заказов, в котором есть список позиций заказа, и каждый заказ связан с клиентом. Требуется номер заказа, общая стоимость элементов заказа и имя клиента. Вы не хотите загружать все позиции заказа и данные клиента для каждого заказа:

var orderDetails = context.Orders
    .Where(o => o.OrderDate >= startDate && o.OrderDate < endDate)
    .Select(o => new OrderViewModel
    {
        OrderId = o.OrderId,
        OrderNumber = o.OrderNumber,
        CustomerName = o.Customer.FullName,
        Total = o.OrderLines.Sum(ol => ol.UnitPrice * ol.Quantity)
    }).ToList();

Это мощная функция EF и Linq, которая помогает гарантировать, что база данных выполняет большую часть работы и возвращает только те поля, которые вам понадобятся. Меньше данных по проводам, меньше памяти на сервере приложений и клиенте.

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

Вы можете использовать аннотации данных, чтобы исключить свойство из модели. Вы можете перейти по этой ссылке: https://docs.microsoft.com/en-us/ef/core/modeling/included-properties чтобы узнать больше. Надеюсь на помощь и с новым годом дружище :))

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    [NotMapped]
    public DateTime LoadedFromDatabase { get; set; }
}

class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>()
            .Ignore(b => b.LoadedFromDatabase);
    }
}

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    public DateTime LoadedFromDatabase { get; set; }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...