【发布时间】:2017-07-20 10:14:08
【问题描述】:
我发现我的应用程序中的一个瓶颈是对一个特定实体的插入操作(通过导航属性插入三个表)。类定义如下:
public class TrackerState
{
public int Id { get; set; }
[Index]
public int TrackerId { get; set; }
[Index]
public DateTime DateRecorded { get; set; }
public DateTime DatePublished { get; set; }
public DateTime DateReceived { get; set; }
public LocationStatus LocationStatus { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }
public double Altitude { get; set; }
public double Accuracy { get; set; }
public string Source { get; set; }
public double Speed { get; set; }
public double Heading { get; set; }
public int PrimaryOdometer { get; set; }
public int SecondaryOdometer { get; set; }
public int OperationalSeconds { get; set; }
public virtual IList<AnalogState> AnalogStates { get; set; }
public virtual IList<DigitalState> DigitalStates { get; set; }
}
public class AnalogState
{
public int TrackerStateId { get; set; }
public virtual TrackerState TrackerState { get; set; }
public int Index { get; set; }
public int Value { get; set; }
}
public class DigitalState
{
public int TrackerStateId { get; set; }
public virtual TrackerState TrackerState { get; set; }
public int Index { get; set; }
public bool Value { get; set; }
}
AnalogState 和 DigitalState 类使用 TrackerStateId 及其索引作为复合主键。
这些表目前非常小:
- TrackerStates:2719
- 模拟状态:0
- 数字状态:32604
当我通过 SQL 管理工作室手动插入表时,操作会在几分之一秒内运行。当我使用以下代码通过 Entity Framework 插入时,最多可能需要 15 秒,所花费的时间很大程度上取决于跟踪器状态中包含的数字值的数量 - 例如具有 0 个数字值的跟踪器状态需要 0.1 到 0.5 秒,具有 64 个数字值的跟踪器状态需要 10 到 15 秒。
public async Task<int> AddAsync(TrackerState trackerState)
{
using (var context = ContextFactory.CreateContext())
{
context.TrackerStates.Add(trackerState);
await context.SaveChangesAsync();
return trackerState.Id;
}
}
基于此,似乎 Entity Framework 在后台执行的操作非常缓慢,但我不知道为什么。考虑到交易的频率,0.5 秒对于交易来说是相当慢的。 15秒实在是太慢了。到目前为止我尝试过的事情都没有成功:
- 禁用更改跟踪。我没想到这会做很多事情,因为无论如何我都在为每个事务使用单独的上下文。
- 首先插入跟踪器状态,然后在单独的步骤中插入数字状态。无论如何,实体框架可能正在内部执行此操作。
更新 1
我正在使用 EntityFramework 6.1.3。我不知道如何查看正在执行的 SQL,但我更新了存储库的 store 方法以使用 SQL 而不是 EF:
context.Database.ExecuteSqlCommand("INSERT INTO DigitalStates ([TrackerStateId], [Index], [Value]) VALUES (@Id, @Index, @Value)",
new SqlParameter("Id", entity.Id),
new SqlParameter("Index", digital.Index),
new SqlParameter("Value", digital.Value));
仅这一部分就占了大部分时间。插入 7 个条目需要 3 秒。
【问题讨论】:
-
是否涉及任何验证?像最大值等?
-
如果您尝试打开 SQL Server Profiler 并查看 EF 正在运行的查询需要 15 秒怎么办?
-
据我所知,输入列没有验证。您在上面的模型中看到的正是用于生成表的内容(除了复合键)。
-
您是否将记录器添加到查询中并查看正在执行的 SQL。还有你运行的是什么版本的 core 或 6?
-
我使用Express Profiler 来查看您的查询 - 简单易用。强烈推荐。
标签: c# entity-framework