EF Eager Loading vs Lazy Loading,性能问题

时间:2017-01-15 18:37:56

标签: c# entity-framework

目前我遇到了一些性能问题。我有27行数据,如果我打开延迟加载并确保没有导航属性,当我执行请求时,我可以看到生成的SQL:

SELECT 
[Extent1].[Id] AS [Id], 
[Extent1].[ExternalId] AS [ExternalId], 
[Extent1].[Name] AS [Name], 
[Extent1].[Description] AS [Description], 
[Extent1].[Address1] AS [Address1], 
[Extent1].[Address2] AS [Address2], 
[Extent1].[Address3] AS [Address3], 
[Extent1].[Address4] AS [Address4], 
[Extent1].[PostCode] AS [PostCode], 
[Extent1].[CollectionPointContact] AS [CollectionPointContact], 
[Extent1].[CollectionPointTelephone] AS [CollectionPointTelephone], 
[Extent1].[CollectionPointFax] AS [CollectionPointFax], 
[Extent1].[CollectionPointEmail] AS [CollectionPointEmail], 
[Extent1].[CompanyId] AS [CompanyId], 
[Extent1].[CreatedById] AS [CreatedById], 
[Extent1].[ModifiedById] AS [ModifiedById], 
[Extent1].[DateCreated] AS [DateCreated], 
[Extent1].[DateModified] AS [DateModified]
FROM [dbo].[Centers] AS [Extent1]

它告诉我它在47ms内执行,在PostMan中需要大约300ms才能执行。这似乎是很长一段时间,但这不是问题。该模型如下所示:

public class Archive
{
    [Required, MaxLength(128)] public string CreatedById { get; set; }
    [Required, MaxLength(128)] public string ModifiedById { get; set; }

    public User CreatedBy { get; set; }
    public User ModifiedBy { get; set; }

    public DateTime DateCreated { get; set; }
    public DateTime DateModified { get; set; }
}

public class Center : Archive
{
    public int Id { get; set; }
    [MaxLength(50)] public string ExternalId { get; set; }
    [Required, MaxLength(150)] public string Name { get; set; }
    [MaxLength(255)] public string Description { get; set; }
    [MaxLength(50)] public string Address1 { get; set; }
    [MaxLength(50)] public string Address2 { get; set; }
    [MaxLength(50)] public string Address3 { get; set; }
    [MaxLength(50)] public string Address4 { get; set; }
    [MaxLength(10)] public string PostCode { get; set; }

    [MaxLength(100)] public string CollectionPointContact { get; set; }
    [MaxLength(50)] public string CollectionPointTelephone { get; set; }
    [MaxLength(50)] public string CollectionPointFax { get; set; }
    [MaxLength(255)] public string CollectionPointEmail { get; set; }

    public int CompanyId { get; set; }
    public Company Company { get; set; }
    public IList<Collection> Collections { get; set; }
}

必须包含的2个导航属性是公司集合,他们的模型如下所示:

public class Company : Archive
{
    public int Id { get; set; }
    [Required, MaxLength(100)]
    public string Name { get; set; }
    public string Logo { get; set; }
    [Required, MaxLength(50)]
    public string Theme { get; set; }

    public IList<User> Members { get; set; }
    public IList<Center> Centers { get; set; }
}

public class Collection : Archive
{
    public int Id { get; set; }
    public int CenterId { get; set; }
    [Required, MaxLength(50)] public string Reference { get; set; }
    [MaxLength(255)] public string Description { get; set; }
    [MaxLength(50)] public string CustomerReference { get; set; }
    [MaxLength(100)] public string CustomerName { get; set; }
    [MaxLength(100)] public string CustomerBusinessName { get; set; }
    [MaxLength(100)] public string SupplierName { get; set; }

    [Column(TypeName="Date")] public DateTime PlannedCollectionDate { get; set; }
    public DateTime DeliveredDate { get; set; }
    public DateTime CollectedDate { get; set; }

    [MaxLength(100)] public string ReceivedBy { get; set; }
    public string ReceivedBySignature { get; set; }

    [MaxLength(100)] public string CollectedBy { get; set; }
    public string CollectedBySignature { get; set; }

    public CollectionStatus Status { get; set; }
}

他们不需要任何导航属性,所以降压停在那里(或至少应该停止)。 如果我使用 Eager Loading 并通过PostMan运行,我可以看到相同的请求在VS内需要355ms,在PostMan中需要大约1300ms(第一次加载似乎总是超过2000ms)。 生成的SQL如下所示:

SELECT 
[Project1].[Id] AS [Id], 
[Project1].[ExternalId] AS [ExternalId], 
[Project1].[Name] AS [Name], 
[Project1].[Description] AS [Description], 
[Project1].[Address1] AS [Address1], 
[Project1].[Address2] AS [Address2], 
[Project1].[Address3] AS [Address3], 
[Project1].[Address4] AS [Address4], 
[Project1].[PostCode] AS [PostCode], 
[Project1].[CollectionPointContact] AS [CollectionPointContact], 
[Project1].[CollectionPointTelephone] AS [CollectionPointTelephone], 
[Project1].[CollectionPointFax] AS [CollectionPointFax], 
[Project1].[CollectionPointEmail] AS [CollectionPointEmail], 
[Project1].[CompanyId] AS [CompanyId], 
[Project1].[CreatedById] AS [CreatedById], 
[Project1].[ModifiedById] AS [ModifiedById], 
[Project1].[DateCreated] AS [DateCreated], 
[Project1].[DateModified] AS [DateModified], 
[Project1].[Id1] AS [Id1], 
[Project1].[Name1] AS [Name1], 
[Project1].[Logo] AS [Logo], 
[Project1].[Theme] AS [Theme], 
[Project1].[CreatedById1] AS [CreatedById1], 
[Project1].[ModifiedById1] AS [ModifiedById1], 
[Project1].[DateCreated1] AS [DateCreated1], 
[Project1].[DateModified1] AS [DateModified1], 
[Project1].[C1] AS [C1], 
[Project1].[Id2] AS [Id2], 
[Project1].[CenterId] AS [CenterId], 
[Project1].[Reference] AS [Reference], 
[Project1].[Description1] AS [Description1], 
[Project1].[CustomerReference] AS [CustomerReference], 
[Project1].[CustomerName] AS [CustomerName], 
[Project1].[CustomerBusinessName] AS [CustomerBusinessName], 
[Project1].[SupplierName] AS [SupplierName], 
[Project1].[PlannedCollectionDate] AS [PlannedCollectionDate], 
[Project1].[DeliveredDate] AS [DeliveredDate], 
[Project1].[CollectedDate] AS [CollectedDate], 
[Project1].[ReceivedBy] AS [ReceivedBy], 
[Project1].[ReceivedBySignature] AS [ReceivedBySignature], 
[Project1].[CollectedBy] AS [CollectedBy], 
[Project1].[CollectedBySignature] AS [CollectedBySignature], 
[Project1].[Status] AS [Status], 
[Project1].[CreatedById2] AS [CreatedById2], 
[Project1].[ModifiedById2] AS [ModifiedById2], 
[Project1].[DateCreated2] AS [DateCreated2], 
[Project1].[DateModified2] AS [DateModified2]
FROM ( SELECT 
    [Extent1].[Id] AS [Id], 
    [Extent1].[ExternalId] AS [ExternalId], 
    [Extent1].[Name] AS [Name], 
    [Extent1].[Description] AS [Description], 
    [Extent1].[Address1] AS [Address1], 
    [Extent1].[Address2] AS [Address2], 
    [Extent1].[Address3] AS [Address3], 
    [Extent1].[Address4] AS [Address4], 
    [Extent1].[PostCode] AS [PostCode], 
    [Extent1].[CollectionPointContact] AS [CollectionPointContact], 
    [Extent1].[CollectionPointTelephone] AS [CollectionPointTelephone], 
    [Extent1].[CollectionPointFax] AS [CollectionPointFax], 
    [Extent1].[CollectionPointEmail] AS [CollectionPointEmail], 
    [Extent1].[CompanyId] AS [CompanyId], 
    [Extent1].[CreatedById] AS [CreatedById], 
    [Extent1].[ModifiedById] AS [ModifiedById], 
    [Extent1].[DateCreated] AS [DateCreated], 
    [Extent1].[DateModified] AS [DateModified], 
    [Extent2].[Id] AS [Id1], 
    [Extent2].[Name] AS [Name1], 
    [Extent2].[Logo] AS [Logo], 
    [Extent2].[Theme] AS [Theme], 
    [Extent2].[CreatedById] AS [CreatedById1], 
    [Extent2].[ModifiedById] AS [ModifiedById1], 
    [Extent2].[DateCreated] AS [DateCreated1], 
    [Extent2].[DateModified] AS [DateModified1], 
    [Extent3].[Id] AS [Id2], 
    [Extent3].[CenterId] AS [CenterId], 
    [Extent3].[Reference] AS [Reference], 
    [Extent3].[Description] AS [Description1], 
    [Extent3].[CustomerReference] AS [CustomerReference], 
    [Extent3].[CustomerName] AS [CustomerName], 
    [Extent3].[CustomerBusinessName] AS [CustomerBusinessName], 
    [Extent3].[SupplierName] AS [SupplierName], 
    [Extent3].[PlannedCollectionDate] AS [PlannedCollectionDate], 
    [Extent3].[DeliveredDate] AS [DeliveredDate], 
    [Extent3].[CollectedDate] AS [CollectedDate], 
    [Extent3].[ReceivedBy] AS [ReceivedBy], 
    [Extent3].[ReceivedBySignature] AS [ReceivedBySignature], 
    [Extent3].[CollectedBy] AS [CollectedBy], 
    [Extent3].[CollectedBySignature] AS [CollectedBySignature], 
    [Extent3].[Status] AS [Status], 
    [Extent3].[CreatedById] AS [CreatedById2], 
    [Extent3].[ModifiedById] AS [ModifiedById2], 
    [Extent3].[DateCreated] AS [DateCreated2], 
    [Extent3].[DateModified] AS [DateModified2], 
    CASE WHEN ([Extent3].[Id] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1]
    FROM   [dbo].[Centers] AS [Extent1]
    INNER JOIN [dbo].[Companies] AS [Extent2] ON [Extent1].[CompanyId] = [Extent2].[Id]
    LEFT OUTER JOIN [dbo].[Collections] AS [Extent3] ON [Extent1].[Id] = [Extent3].[CenterId]
)  AS [Project1]
ORDER BY [Project1].[Id] ASC, [Project1].[Id1] ASC, [Project1].[C1] ASC

这对我来说似乎有些奇怪,但我会假设EF知道它在做什么。 无论如何,添加集合和公司使请求平均大约1秒,但在第一次加载时它通常是2s +。

如果我然后停用预先加载并切换到延迟加载,并确保公司收藏都是虚拟属性存在一些差异。 主要区别在于,现在所有集合公司都作为单独的SQL语句加载,这显然会增加加载时间。 在PostMan中,第一个加载时间超过4秒,之后的每个请求大约为3秒。 因此,在这种情况下,渴望加载是优越的,但仍然在一秒钟内拉入271条记录似乎很长一段时间。我想比这更多地提高性能。 那么,有人可以就如何解决这个问题提出一些建议吗?

0 个答案:

没有答案