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

Posted

技术标签:

【中文标题】在实体框架中设置数据库超时【英文标题】:Set database timeout in Entity Framework 【发布时间】:2012-09-29 03:09:25 【问题描述】:

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

我找到了myDb.Database.Connection.ConnectionTimeout,但它是readonly

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

【问题讨论】:

仅供参考,在 EF6 上,Database.CommandTimeout 不再是只读的 @itsho 他说的是Database.Connection.ConnectionTimeout。无论如何,如果您的查询超时,我会说Database.CommandTimeout 是正确的(例外System.Data.Entity.Core.EntityCommandExecutionException 包含System.Data.SqlClient.SqlException: Timeout expired.)。 Entity Framework Timeouts的可能重复 我假设您实际上并不关心 CONNECTION 超时,而是您想调整 COMMAND 超时。 【参考方案1】:

在你的上下文中试试这个:

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>

来源:How to: Define the Connection String

【讨论】:

我建议您使用连接字符串版本,就像您尝试在此构造函数中访问 ObjectContext 有时访问 PowerShell/NuGet console commands will fail in a circular way 一样。 连接超时和命令超时以及两个不同的东西。连接字符串设置 Connection Timeout 不会影响命令运行的时间量 (CommandTimeout)。 我的问题有点不同。我在迁移期间超时。 EF 有一个类似的属性可以设置为在迁移期间使用:msdn.microsoft.com/en-us/library/… 根据您使用的 EF 版本,请参阅this answer 了解如何指定 CommandTimeout 属性的不同 API。 对我不起作用(我怀疑连接与命令不是一回事)。这篇文章虽然解决了它***.com/questions/6232633/entity-framework-timeouts【参考方案2】:

我的部分上下文如下所示:

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 public,所以我只修改了我需要花费很长时间(超过 5 分钟)的例程,而不是全局超时。

【讨论】:

【参考方案3】:

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

static class Extensions

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

【讨论】:

我该如何调用这个扩展方法?【参考方案4】:

我用流畅的实现扩展了 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));
     

【讨论】:

【参考方案5】:

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

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

partial class MyContext: ObjectContext

    partial void OnContextCreated()
    
        this.CommandTimeout = 300;
    

【讨论】:

【参考方案6】:

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

这很简单,不需要演员表。

【讨论】:

对使用Fluent API EF 形式的我们非常有用。【参考方案7】:

对于数据库优先方法:

我们仍然可以在构造函数中设置它,通过这种方式覆盖 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;

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

【讨论】:

有什么方法可以使用一些配置文件在模板中指定超时时间? 不确定,是否有内置内容(我无法找到某些内容)。但是你可以使用System.Configuration.ConfigurationManager.AppSettings["keyname"]@shas,而不是硬编码 180【参考方案8】:

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

【讨论】:

【参考方案9】:

我刚刚遇到了这个问题,并通过更新我的应用程序配置文件解决了这个问题。对于有问题的连接,指定“Connection Timeout=60”(我使用的是实体框架版本 5.0.0.0)

ConnectionTimeout Setting

【讨论】:

【参考方案10】:

您应该在 web 配置中的 Connection String 标记中进行更改,并让 EntityFrameWork 在其构造函数中从中读取。

    将此术语添加到 web.config 连接字符串: 连接超时=300;

    在构造函数中添加如下代码:

    Database.CommandTimeout = 数据库.Connection.ConnectionTimeout;

通过这种方法,您将使用户能够控制超时,而无需为他进行新的发布。

【讨论】:

如前所述:连接超时!= 命令超时。命令超时在这里很重要。 这种方法是从连接字符串中动态读取,而不是单独设置。 那个细节没有让我看到,这立即表明了这种黑客行为的问题。这是完全出乎意料的,永远不应该这样做。 黑客检查应该从其他地方完成,我认为命令的命令超时时间应该足够长以执行长查询或 SQL 命令。因此,网站管理员应该能够根据自己的需要控制此时间段,而无需仅仅更改命令超时时间段而获得新的发布。 不要滥用连接字符串中的 Connection Timeout 设置!下一个应用程序管理器会将其设置为其他值,而不会意识到它的含义。而且,请记住,它设置连接超时(显然)。如果由于某些意外情况碰巧连接不可用,您不希望人们等待 5 分钟。

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

如何在实体框架中设置默认值

实体框架不遵守命令超时

如何在实体框架中设置 SQL Server 2008 的登录信息?

如何首先在实体框架代码中设置身份主键的起始值?

如何在连接字符串中设置实体框架 4 CommandTimeout?

在实体框架中设置 HTML <input> step 属性