实体框架超时

Posted

技术标签:

【中文标题】实体框架超时【英文标题】:Entity Framework Timeouts 【发布时间】:2011-09-08 03:00:36 【问题描述】:

在使用需要超过 30 秒才能完成的函数导入时,我使用实体框架 (EF) 出现超时。我尝试了以下方法,但未能解决此问题:

我将Default Command Timeout=300000 添加到项目的App.Config 文件中的连接字符串中,该文件具有建议的here 的EDMX 文件。

这是我的连接字符串的样子:

<add 
    name="MyEntityConnectionString" 
    connectionString="metadata=res://*/MyEntities.csdl|res://*/MyEntities.ssdl|
       res://*/MyEntities.msl;
       provider=System.Data.SqlClient;provider connection string=&quot;
       Data Source=trekdevbox;Initial Catalog=StarTrekDatabase;
       Persist Security Info=True;User ID=JamesTKirk;Password=IsFriendsWithSpock;
       MultipleActiveResultSets=True;Default Command Timeout=300000;&quot;"
    providerName="System.Data.EntityClient" />

我尝试像这样直接在我的存储库中设置 CommandTimeout:

private TrekEntities context = new TrekEntities();

public IEnumerable<TrekMatches> GetKirksFriends()

    this.context.CommandTimeout = 180;
    return this.context.GetKirksFriends();

我还能做些什么来让 EF 避免超时?这只发生在非常大的数据集上。小型数据集一切正常。

这是我遇到的错误之一:

System.Data.EntityCommandExecutionException:执行命令定义时出错。有关详细信息,请参阅内部异常。 ---> System.Data.SqlClient.SqlException:超时已过期。在操作完成之前超时时间已过或服务器没有响应。


好的 - 我得到了这个工作,发生的事情很愚蠢。我将Default Command Timeout=300000 的连接字符串和CommandTimeout 设置为180。当我从连接字符串中删除Default Command Timeout 时,它起作用了。因此,答案是在您的上下文对象的存储库中手动设置 CommandTimeout,如下所示:

this.context.CommandTimeout = 180;

显然在连接字符串中设置超时设置对它没有影响。

【问题讨论】:

删除 "从连接字符串 也可以参考这个***.com/questions/4396833/sql-exception-with-net-4-ef @hamlin11 在 EF 连接字符串中,需要定义什么部分是连接字符串以及什么部分是 EF 元数据。将&amp;quot; 留在字符串中。 我的建议是在增加超时之前先调查一下 EF 超时的原因。在我们的案例中,我们意识到我们需要为一些表添加NONCLUSTERED 索引,这为我们解决了超时问题。 我正在与 MS 支持部门合作解决 SQL 超时问题 - 这是当数据库托管在 SQL Azure 中时。我被告知所有 Azure PaaS 服务(PaaS 网站和 SQL Azure 等)都有 230 秒的通用超时,即使您手动设置了超时,这始终优先。这是为了保护多租户 PaaS 基础架构的资源。 【参考方案1】:

在 EF 连接字符串中指定默认命令超时存在一个已知错误。

http://bugs.mysql.com/bug.php?id=56806

从连接字符串中删除值并将其设置在数据上下文对象本身上。如果您从连接字符串中删除冲突值,这将起作用。

实体框架核心 1.0:

this.context.Database.SetCommandTimeout(180);

实体框架 6:

this.context.Database.CommandTimeout = 180;

实体框架 5:

((IObjectContextAdapter)this.context).ObjectContext.CommandTimeout = 180;

Entity Framework 4 及以下:

this.context.CommandTimeout = 180;

【讨论】:

如何使用 edmx 实现这一点? 在哪个版本的 EntityFramework 中修复了这个问题?我找不到它的 EF 错误。 我不认为这是一个错误,而是设计使然,请参阅此处的备注部分 link 因为有些设置是ms,有些是s,所以我查了here,CommandTimeout是以秒为单位的。 在 Entity Framework 7 中,您可以在 DbContext / IdentityDbContext 的构造函数中进行设置:this.Database.SetCommandTimeout(180);【参考方案2】:

如果您使用的是 DbContext,请使用以下构造函数来设置命令超时:

public class MyContext : DbContext

    public MyContext ()
    
        var adapter = (IObjectContextAdapter)this;
        var objectContext = adapter.ObjectContext;
        objectContext.CommandTimeout = 1 * 60; // value in seconds
    

【讨论】:

@ErickPetru,因此您可以轻松地将其更改为不同的分钟数 :),如果编译器优化了该乘法,我也不会太惊讶! @JoelVerhagen,不要感到惊讶。以下是对何时发生自动优化的一个很好的解释:***.com/questions/160848/…。在这种情况下,我认为甚至会发生(因为它们是两个文字值​​),但老实说,我认为这样的代码有点奇怪。 meh...孩子们在挨饿...谁在乎 1*60? @ErikPetru,这实际上是一种非常普遍的做法,并且使代码更具可读性。 鉴于我的 DbContext 派生类是从 edmx 文件自动生成的,处理此问题的最佳方法是什么?【参考方案3】:

如果您使用的是DbContext 和 EF v6+,您也可以使用:

this.context.Database.CommandTimeout = 180;

【讨论】:

【参考方案4】:

我通常在事务中处理我的操作。正如我所经历的那样,设置上下文命令超时是不够的,但事务需要一个带有超时参数的构造函数。我必须设置两个超时值才能正常工作。

int? prevto = uow.Context.Database.CommandTimeout;
uow.Context.Database.CommandTimeout = 900;
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, TimeSpan.FromSeconds(900))) 
...

在函数结束时,我将命令超时设置回 prevto 中的前一个值。

使用 EF6

【讨论】:

根本不是一个好方法。我曾经添加很多事务范围,这对我来说是一个项目中的噩梦。最终在 EF 6+ 中用单个 SAVEChanges() 替换了所有事务范围。检查这个coderwall.com/p/jnniww/… 这个答案应该有更高的投票。我尝试了所有不同的方法来增加超时,但只有当我同时设置上下文命令超时和事务范围时它才会起作用。【参考方案5】:

如果你像我一样使用实体框架,你应该定义 Time out on Startup 类如下:

 services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"), o => o.CommandTimeout(180)));

【讨论】:

【参考方案6】:

我知道这是一个非常老的线程运行,但 EF 仍然没有解决这个问题。对于使用自动生成的DbContext 的人可以使用以下代码手动设置超时。

public partial class SampleContext : DbContext

    public SampleContext()
        : base("name=SampleContext")
    
        this.SetCommandTimeOut(180);
    

    public void SetCommandTimeOut(int Timeout)
    
        var objectContext = (this as IObjectContextAdapter).ObjectContext;
        objectContext.CommandTimeout = Timeout;
    

【讨论】:

在部分末尾添加您缺少的 。【参考方案7】:

.Net Core (NetCore) 中使用以下语法将超时时间从默认的 30 秒更改为 90 秒:

public class DataContext : DbContext

    public DataContext(DbContextOptions<DataContext> options) : base(options)
    
        this.Database.SetCommandTimeout(90); // <-- 90 seconds
    

【讨论】:

【参考方案8】:

这是我出资的。也许它会对某人有所帮助:

所以我们开始:

如果您使用带有 EF 的 LINQ 来查找列表中包含的一些确切元素,如下所示:

await context.MyObject1.Include("MyObject2").Where(t => IdList.Contains(t.MyObjectId)).ToListAsync();

一切正常,直到 IdList 包含多个 Id。

如果列表只包含一个 ID,就会出现“超时”问题。要解决此问题,请使用 if 条件检查 IdList 中的 id 数。

例子:

if (IdList.Count == 1)

    result = await entities. MyObject1.Include("MyObject2").Where(t => IdList.FirstOrDefault()==t. MyObjectId).ToListAsync();

else

    result = await entities. MyObject1.Include("MyObject2").Where(t => IdList.Contains(t. MyObjectId)).ToListAsync();

解释:

只需尝试使用 Sql Profiler 并检查 Entity frameeork 生成的 Select 语句。 …

【讨论】:

【参考方案9】:

将以下内容添加到我的存储过程中,我解决了超时错误:

SET NOCOUNT ON;
SET ARITHABORT ON;

【讨论】:

【参考方案10】:

对于实体框架 6,我使用此注释并且工作正常。

  public partial class MyDbContext : DbContext
  
      private const int TimeoutDuration = 300;

      public MyDbContext ()
          : base("name=Model1")
      
          this.Database.CommandTimeout = TimeoutDuration;
      
       // Some other codes
    

CommandTimeout 参数是一个可以为空的整数,用于设置超时 值作为秒,如果您设置 null 或不设置它将使用默认值 您使用的提供者的价值。

【讨论】:

【参考方案11】:

你可以在连接字符串中设置2个超时参数

超时=300;CommandTimeout=300;

Host=localhost;Port=5432;database=mydatabase;username=postgres;password=postgres;Timeout=300;CommandTimeout=300;

一个用于命令,一个用于连接。

【讨论】:

以上是关于实体框架超时的主要内容,如果未能解决你的问题,请参考以下文章

实体框架不遵守命令超时

在实体框架中设置数据库超时

为啥 SQL Express 上的实体框架会忽略超时?

使用 SQL Azure 从会话状态提供程序(实体框架)持续接收“超时时间已过”

实体框架中的连接泄漏

如何确定实体框架是不是正在等待来自连接池的连接?