在 Entity Framework 中设置数据库超时时间

181

我的命令一直超时,因此我需要更改默认的命令超时值。

我找到了 myDb.Database.Connection.ConnectionTimeout,但它是只读的。

我该如何在 Entity Framework 5 中设置命令超时?


20
FYI,在EF6中,Database.CommandTimeout不再是只读的。 - itsho
2
@itsho 他在谈论 Database.Connection.ConnectionTimeout。无论如何,我认为如果你的查询超时(异常 System.Data.Entity.Core.EntityCommandExecutionException 包含 System.Data.SqlClient.SqlException: Timeout expired.),那么 Database.CommandTimeout 才是正确的选择。 - David Ferenczy Rogožan
3
可能是Entity Framework超时问题的重复问题。 - Tim Pohlmann
2
我假设你实际上并不关心连接超时,而是想要调整命令超时。 - Worthy7
11个回答

220

在您的上下文中尝试此方法:

public class MyDatabase : DbContext
{
    public MyDatabase ()
        : base(ContextHelper.CreateConnection("Connection string"), true)
    {
        ((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 180; // seconds
    }
}
如果你想在连接字符串中定义超时时间,可以使用Connection Timeout参数,就像下面的连接字符串一样:
<connectionStrings>

<add name="AdventureWorksEntities"
connectionString="metadata=.\AdventureWorks.csdl|.\AdventureWorks.ssdl|.\AdventureWorks.msl;
provider=System.Data.SqlClient;provider connection string='Data Source=localhost;
Initial Catalog=AdventureWorks;Integrated Security=True;Connection Timeout=60;
multipleactiveresultsets=true'" providerName="System.Data.EntityClient" />

</connectionStrings>

来源:如何定义连接字符串


1
我建议使用连接字符串版本,因为如果您尝试在此构造函数中访问 ObjectContext,有时PowerShell/NuGet控制台命令会以循环方式失败 - Kevin Gorski
144
连接超时和命令超时是两个不同的概念。连接字符串中的"连接超时"设置不会影响命令执行的时间(命令超时)。 - Clay Lenhart
3
我的问题与众不同,我在进行迁移时遇到了超时问题。EF有一个类似的属性可用于设置迁移期间的超时:http://msdn.microsoft.com/en-us/library/system.data.entity.migrations.dbmigrationsconfiguration.commandtimeout - Karsten
2
根据您使用的EF版本,参见此答案以了解如何指定CommandTimeout属性中不同API的感觉。 - Jim Aho
1
我的连接超时设置正常,但发现 CommandTimeout 为空。我按照 @leniel-macaferi 的建议设置了 CommandTimeout,并解决了超时问题。-因此它们不是同一件事,并且都需要设置才能在 EF 中启用自定义超时。 - Nebu
显示剩余5条评论

201

您可以使用DbContext.Database.CommandTimeout = 180; // seconds

这非常简单,无需进行类型转换。


2
对于我们使用 EF 的 Fluent API 形式非常有用。 - GoldBishop

21

我的部分上下文如下:

public partial class MyContext : DbContext
{
    public MyContext (string ConnectionString)
        : base(ConnectionString)
    {
        this.SetCommandTimeOut(300);
    }

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

我将SetCommandTimeOut设置为公共函数,这样只有需要执行时间长(超过5分钟)的程序才会被修改,而不是全局超时。


10

在生成的构造函数代码中,应该调用 OnContextCreated()

我添加了这个部分类来解决问题:

partial class MyContext: ObjectContext
{
    partial void OnContextCreated()
    {
        this.CommandTimeout = 300;
    }
}

9

针对数据库优先的方法:

我们仍然可以通过重写ContextName.Context.tt T4模板中的构造函数来设置它,方法如下:

<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext
{
    public <#=code.Escape(container)#>()
        : base("name=<#=container.Name#>")
    {
        Database.CommandTimeout = 180;
<#
if (!loader.IsLazyLoadingEnabled(container))
{
#>
        this.Configuration.LazyLoadingEnabled = false;
<#
}

Database.CommandTimeout = 180; 是实际的更改。

生成的输出如下:

public ContextName() : base("name=ContextName")
{
    Database.CommandTimeout = 180;
}

如果您更改数据库模型,此模板将保留,但实际的类将被更新。

我们是否可以通过某个配置文件在模板中指定超时时间? - shas
1
我不确定是否有现成的东西可用(我找不到相关信息)。但是,你可以使用System.Configuration.ConfigurationManager.AppSettings[“keyname”]代替直接硬编码数字180。 @shas - Christian Gollhardt

9
我用流畅的实现扩展了Ronnie的答案,这样你就可以像下面这样使用它: dm.Context.SetCommandTimeout(120).Database.SqlQuery...
public static class EF
{
    public static DbContext SetCommandTimeout(this DbContext db, TimeSpan? timeout)
    {
        ((IObjectContextAdapter)db).ObjectContext.CommandTimeout = timeout.HasValue ? (int?) timeout.Value.TotalSeconds : null;

        return db;
    }

    public static DbContext SetCommandTimeout(this DbContext db, int seconds)
    {
        return db.SetCommandTimeout(TimeSpan.FromSeconds(seconds));
    } 
}

8
与其他答案相同,但作为扩展方法:

与其他答案相同,但作为扩展方法:

static class Extensions
{
    public static void SetCommandTimeout(this IObjectContextAdapter db, TimeSpan? timeout)
    {
        db.ObjectContext.CommandTimeout = timeout.HasValue ? (int?) timeout.Value.TotalSeconds : null;
    }
}

我该如何调用这个扩展方法? - Wanderson López

1
你可以使用这个简单的方法:
dbContext.Database.SetCommandTimeout(300);

1
我遇到了这个问题,通过更新我的应用程序配置文件来解决它。对于所涉及的连接,请指定“Connection Timeout=60”(我正在使用实体框架版本5.0.0.0)。 连接超时设置

连接超时不等于命令超时! - Gert Arnold

0
在我的情况下,连接字符串属性是只读的。此外,实体构造函数是自动生成的,因此我不想把它放在那里。另外,在构造函数中放置会应用于所有存储过程,而我只需要在一个存储过程中使用它。
以下是我的解决方法。
try
     { using (MyEntities Mydb = new MyEntities())
       {
         (Mydb as System.Data.Entity.Infrastructure.IObjectContextAdapter).ObjectContext.CommandTimeout = 600;
         Mydb.LongRunningSproc();
        }
      }
  catch (System.Data.Common.DbException ex)
      {
          throw new Exception(SomeMessageHere);
      }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接