c# - Entity Framework 在调用 INSERT 之前加载所有行

标签 c# .net entity-framework

我有一些我认为效率不高的 Entity Framework 代码。基本上,我有一个如下所示的 ApplicationUser 类:

public class ApplicationUser : IdentityUser
{
   public string CompanyName { get; set; }
   public virtual ICollection<SolverRun> Runs { get; set; }

   // .. other stuff generated by the Visual Studio template
}

我想做的是在 SolverRuns 中为当前用户创建一个新行:

// Log run in database
var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
var currentUser = manager.FindById(OwnerId);
currentUser.Runs.Add(new SolverRun
{
   Base = job.Base,
   Duration = context.JobRunTime,
   Result = (context.Result ?? "").ToString(),
   RunName = job.RunName,
   Start = context.FireTimeUtc.GetValueOrDefault().LocalDateTime
});

manager.Update(currentUser);

这很好用。但是,我看到的是以下查询:

exec sp_executesql N'SELECT 
    [Extent1].[SolverRunID] AS [SolverRunID], 
    [Extent1].[RunName] AS [RunName], 
    [Extent1].[Base] AS [Base], 
    [Extent1].[Start] AS [Start], 
    [Extent1].[Duration] AS [Duration], 
    [Extent1].[Result] AS [Result], 
    [Extent1].[ApplicationUser_Id] AS [ApplicationUser_Id]
    FROM [dbo].[SolverRuns] AS [Extent1]
    WHERE ([Extent1].[ApplicationUser_Id] IS NOT NULL) AND ([Extent1].[ApplicationUser_Id] = @EntityKeyValue1)',N'@EntityKeyValue1 nvarchar(128)',@EntityKeyValue1=N'029a20a9-b487-4579-87d0-50608ed7f058'

这将为该用户选择 SolverRuns 表中的每一行。我怀疑 getter currentUser.Runs 发生了这种情况。

我担心随着用户添加越来越多的运行(最终可能有数千次),这会变得越来越慢。有没有办法只添加新行,而不是先选择所有内容?谢谢!

更新:

根据下面 py3r3str 的回答,这是我的新工作代码(在更改模型和迁移数据库等之后):

// Log run in database
using (var dbContext = new ApplicationDbContext())
{
   var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(dbContext));
   var currentUser = manager.FindById(job.OwnerId);

   dbContext.Set<SolverRun>().Add(new SolverRun
   {
      Base = job.Base,
      Duration = context.JobRunTime,
      Result = (context.Result ?? "").ToString(),
      RunName = job.RunName,
      Start = context.FireTimeUtc.GetValueOrDefault().LocalDateTime,
      ApplicationUser = currentUser
   });

   dbContext.SaveChanges();
}

它现在将运行此 INSERT 语句(这很奇怪,但我放弃了尝试理解 EF SQL 查询,所以我假设比我聪明的人认为它是有效的):

exec sp_executesql N'INSERT [dbo].[SolverRuns]([ApplicationUserId], [RunName], [Base], [Start], [Duration], [Result])
VALUES (@0, @1, @2, @3, @4, @5)
SELECT [SolverRunID]
FROM [dbo].[SolverRuns]
WHERE @@ROWCOUNT > 0 AND [SolverRunID] = scope_identity()',N'@0 nvarchar(128),@1 nvarchar(max) ,@2 nvarchar(max) ,@3 datetime2(7),@4 time(7),@5 nvarchar(max) ',@0=N'029a20a9-b487-4579-87d0-50608ed7f058',@1=N'PilotRun',@2=N'YUL',@3='2015-09-03 11:07:32.0353181',@4='00:00:04.1521401',@5=N'Success'

请注意,调用 currentUser.Runs 将按预期延迟加载所有运行。

最佳答案

最简单的方法之一是将外键添加到您的 SolverRun 实体:

class SolverRun
{
    ...
    public string ApplicationUserId { get; set; }

    [ForeignKey("ApplicationUserId")]
    public virtual ApplicationUser ApplicationUser { get; set; }
}

并且仅使用 ApplicationContext 保存 SolverRun 实体:

var solverRun = new SolverRun
{
    Base = job.Base,
    Duration = context.JobRunTime,
    Result = (context.Result ?? "").ToString(),
    RunName = job.RunName,
    Start = context.FireTimeUtc.GetValueOrDefault().LocalDateTime,
    ApplicationUserId = OwnerId
};
dbContext.Set<SolverRun>().Add(solverRun);
dbContext.SaveChanges();

在这种情况下,EF 还会在 ApplicationUser.Runs 中添加对象。

关于c# - Entity Framework 在调用 INSERT 之前加载所有行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32381829/

相关文章:

c# - 使用后台线程生成的 RenderTargetBitmap 设置图像源

c# - 提交,显示结果,延迟 3 秒并重定向

c# - 使用 Entity Framework 从表中获取多个数据

c# - .NET 编码与字符集的关系

c# - AutoMapper 条件实体映射

c# - 不同文化的日期时间转换

c# - 如何找到未使用 PrincipalSearcher 设置属性的 UserPrincipal?

entity-framework - 获取输出参数值

c# - 声明数据库变量的良好做法

c# - 无法将字符串转换为 XML