实体框架超时


324

使用功能导入需要超过30秒才能完成时,使用实体框架(EF)导致超时。我尝试了以下操作,但无法解决此问题:

Default Command Timeout=300000这里建议的具有EDMX文件的项目的App.Config文件中添加了连接字符串。

这是我的连接字符串如下所示:

<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;

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


删除“ 来自连接字符串
Brian Webster


5
@ hamlin11在EF连接字符串中,需要定义哪个部分是连接字符串以及哪个部分是EF元数据。留&quot;在字符串中。
CHEV

2
我的建议是在您增加超时之前,请先进行调查,以了解EF为什么会超时。在我们的案例中,我们意识到我们需要向NONCLUSTERED一些表中添加索引,这为我们解决了超时问题。
zulucoda 2014年

我正在与MS支持合作处理SQL超时问题-这是将数据库托管在SQL Azure中的时候。有人告诉我所有Azure PaaS服务(PaaS网站和SQL Azure等)的通用超时时间为230秒,即使您手动设置超时,该超时也始终优先。这是为了保护多租户PaaS基础架构的资源。
伊恩·罗伯逊

Answers:


552

在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;

实体框架4及以下版本:

this.context.CommandTimeout = 180;

5
如何使用edmx实现此目的?
iroel 2014年

2
在哪个版本的EntityFramework中已修复?我找不到它的EF错误。
rudimenter 2015年

7
我不认为这是错误,而是设计使然,请参阅“备注”部分链接
Mick P

3
因为某些设置以ms为单位,而有些则以s为单位,所以我在这里进行了查找,CommandTimeout的单位为秒。
JabberwockyDecompiler 2015年

6
在Entity Framework 7中,您可以在DbContext / IdentityDbContext的构造函数中进行设置:this.Database.SetCommandTimeout(180);
ThomasHagström,2016年

101

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

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

3
@ErickPetru,因此您可以轻松地将其更改为不同的分钟数:),如果编译器优化该乘法,我也不会感到惊讶!
Joel Verhagen

2
@JoelVerhagen,不要惊讶。这是有关何时进行自动优化的很好的解释:stackoverflow.com/questions/160848/…。在这种情况下,我认为甚至会发生(因为它们是两个字面值),但老实说,我认为代码有点奇怪。
Erick Petrucelli

33
嗯...孩子饿了...谁在乎1 * 60?
Timmerz 2013年

9
@ErikPetru,这实际上是非常普遍的做法,它使代码更具可读性。
加尔文(Calvin)2013年

鉴于我的DbContext派生类是从edmx文件自动生成的,处理此问题的最佳方法是什么?
马特·伯兰德

41

如果使用的是DbContextEF v6 +,则可以使用:

this.context.Database.CommandTimeout = 180;

13

通常,我在交易中处理我的操作。以我的经验,仅设置上下文命令超时是不够的,但是事务需要一个带有timeout参数的构造函数。我必须设置两个超时值才能使其正常工作。

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/…–
月亮

这个答案应该有更高的投票权。我尝试了各种增加超时的方法,但是只有当我同时设置了上下文命令超时和事务作用域时,它才起作用。

3

我知道这是运行很旧的线程,但是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;
    }

3

如果您像我一样使用Entity Framework,则应按以下方式定义“启动时超时”类:

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

1

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

所以我们开始:

如果您将LINQ与EF结合使用,则查找列表中包含的某些确切元素,如下所示:

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语句。…

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.