【问题标题】:Entity Framework is executing too many queries实体框架正在执行太多查询
【发布时间】:2013-04-23 15:04:12
【问题描述】:

我需要找到特定用户的不同广告系列。用户拥有 CodeRights,CodeRights 包含 Codes,Codes 包含 Campaign。这是 CodeRight 类

public class SmartCodeRight
{
        [Key, Column(Order = 1)]
        public long UserId { get; set; }
        public virtual User User { get; set; }

        [Key, Column(Order = 2)]
        public long CodeId { get; set; }
        public virtual SmartCode Code { get; set; }

        public CodeRight CodeRight { get; set; }
}

我会为此编写以下 SQL:

SELECT * 
FROM campaigns 
WHERE campaignid IN (SELECT DISTINCT campaignid  
                     FROM smartcodes t1 
                     INNER JOIN smartcoderights t2 ON t1.codeId = t2.codeId
                     WHERE t2.userid = @userId)

我正在使用 EF 编写此代码:

var v = user.CodeRights.Select(r => r.Code.Campaign).Distinct().ToList();

现在在分析时,我看到 EF 正在为每个存在的 CodeRight 执行 2 个 SQL 查询。

我还计算了整个执行的时间,EF 大约需要 400 毫秒,而使用 ADO.Net 时只有大约 8 毫秒

现在我的问题是,如果 EF 真的这么慢还是我做错了什么?

编辑

为每个 CodeRight 执行以下两个块

exec sp_executesql N'SELECT 
[Extent1].[CodeId] AS [CodeId], 
[Extent1].[CodeTitle] AS [CodeTitle], 
[Extent1].[CodeContent] AS [CodeContent], 
[Extent1].[CreatedOn] AS [CreatedOn], 
[Extent1].[IsActive] AS [IsActive], 
[Extent1].[Deleted] AS [Deleted], 
[Extent1].[OwnerId] AS [OwnerId], 
[Extent1].[Tags] AS [Tags], 
[Extent1].[CampaignId] AS [CampaignId]
FROM [dbo].[SmartCodes] AS [Extent1]
WHERE [Extent1].[CodeId] = @EntityKeyValue1',N'@EntityKeyValue1 bigint',@EntityKeyValue1=24
go

exec sp_executesql N'SELECT 
[Extent1].[CampaignId] AS [CampaignId], 
[Extent1].[Name] AS [Name], 
[Extent1].[Description] AS [Description], 
[Extent1].[AdminId] AS [AdminId]
FROM [dbo].[Campaigns] AS [Extent1]
WHERE [Extent1].[CampaignId] = @EntityKeyValue1',N'@EntityKeyValue1 int',@EntityKeyValue1=12
go

【问题讨论】:

  • 你能显示执行查询的代码吗?这个问题 (stackoverflow.com/questions/8473705/…) 表明 EF 应该使用 DISTINCT 生成正确的查询
  • ORM 的权衡是它们“健谈”。大多数时候,性能“足够好”。但他们很健谈。但是您花费更少的时间编写自定义 ORM 代码。选择毒药。您可以做的是查看 EF 如何发出查询并查看是否有值得添加的索引。
  • @w.brian 请查看编辑。
  • 您还没有将这些项目设置为外键,但不确定这是否会有所不同。
  • @mattytommo 所有外键均已正确配置。我已经交叉检查了数据库。

标签: c# sql-server asp.net-mvc performance entity-framework


【解决方案1】:

您应该花时间查看Fetch Plans for Entity Framework。为了让 EF 执行连接,您必须使用 Include 关键字。

当您获得 user 对象时,它必须是您初始查询的一部分:

var user = context.Users
    .Include("CodeRights.Code")
    .Include("CodeRights.Campaign")
    .FirstOrD‌​efault(u => u.Id == id);

【讨论】:

  • CodeRights 是 CodeRight 类型的集合,因此不能有“包含”。
  • Include 需要成为返回用户的查询的一部分,例如 var user = context.Users.Include("CodeRights.Code").Include("CodeRights.Campaign").FirstOrDefault(u => u.Id == id);
  • @DmitryStarosta 好声音,没发现。更新:)
  • 喜欢这个var v = db.SmartCodeRights.Where(r => r.UserId == user.UserId).Include(r => r.Code).Include(r => r.Code.Campaign).Select(r => r.Code.Campaign).Distinct().ToList(); 现在只是一个查询。不想包含在第一个查询中,因为它会带来不必要的数据。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-11
  • 1970-01-01
相关资源
最近更新 更多