Đặt thời gian chờ cơ sở dữ liệu trong Entity Framework


164

Lệnh của tôi tiếp tục hết thời gian, vì vậy tôi cần thay đổi giá trị thời gian chờ lệnh mặc định.

Tôi đã tìm thấy myDb.Database.Connection.ConnectionTimeout, nhưng nó readonly.

Làm cách nào tôi có thể đặt thời gian chờ lệnh trong Entity Framework 5 ?


20
FYI, trên EF6, Database.CommandTimeoutkhông còn chỉ đọc
itho

2
@itsho Anh đang nói về Database.Connection.ConnectionTimeout. Dù sao, tôi sẽ nói rằng đó Database.CommandTimeoutlà điều đúng trong trường hợp truy vấn của bạn hết thời gian ( System.Data.Entity.Core.EntityCommandExecutionExceptioncó chứa ngoại lệ System.Data.SqlClient.SqlException: Timeout expired.).
David Ferenczy Rogožan

2
Bản sao có thể có của Thời gian chờ khung thực thể
Tim Pohlmann

1
Tôi cho rằng bạn thực sự không quan tâm đến thời gian chờ kết nối, nhưng thay vào đó bạn muốn điều chỉnh thời gian chờ LỆNH.
Worthy7

Câu trả lời:


199

Hãy thử điều này trên bối cảnh của bạn:

public class MyDatabase : DbContext
{
    public MyDatabase ()
        : base(ContextHelper.CreateConnection("Connection string"), true)
    {
        ((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 180;
    }
}

Nếu bạn muốn xác định thời gian chờ trong chuỗi kết nối, hãy sử dụng Connection Timeouttham số như trong chuỗi kết nối sau:

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

Nguồn: Cách: Xác định chuỗi kết nối


1
Tôi khuyên bạn nên sử dụng phiên bản chuỗi kết nối vì nếu bạn cố gắng truy cập vào hàm tạo ObjectContextnày đôi khi các lệnh của bảng điều khiển PowerShell / NuGet sẽ thất bại theo cách vòng tròn .
Kevin Gorski

130
Hết thời gian kết nối và CommandTimeout và hai thứ riêng biệt. Cài đặt chuỗi kết nối, Hết thời gian kết nối, sẽ không ảnh hưởng đến lượng thời gian lệnh chạy (CommandTimeout).
Clay Lenhart

3
Vấn đề của tôi là một sự khác biệt. Tôi đã hết thời gian trong quá trình di chuyển. EF có một thuộc tính tương tự để thiết lập để sử dụng trong quá trình di chuyển: msdn.microsoft.com/en-us/l Library / từ
Karsten

2
Tùy thuộc vào phiên bản EF bạn sử dụng, hãy xem câu trả lời này để cảm nhận về các API khác nhau trong cách chỉ định thuộc tính CommandTimeout.
Jim Aho

1
Không hoạt động đối với tôi (Kết nối và Lệnh không phải là điều tôi nghi ngờ). Bài đăng này đã giải quyết nó mặc dù stackoverflow.com/questions/6232633/entity-framework-timeouts
Jezbers

181

Bạn có thể dùng DbContext.Database.CommandTimeout = 180;

Nó khá đơn giản và không cần diễn viên.


1
Rất hữu ích cho chúng tôi sử dụng Fluent APIhình thức của EF.
GoldBishop

20

Bối cảnh một phần của tôi trông như:

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

Tôi đã để SetCommandTimeOutcông khai nên chỉ những thói quen tôi cần mất nhiều thời gian (hơn 5 phút) tôi sửa đổi thay vì hết thời gian trên toàn cầu.


9

Trong mã xây dựng được tạo, nó sẽ gọi OnContextCreated()

Tôi đã thêm lớp một phần này để giải quyết vấn đề:

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

8

Tôi đã mở rộng câu trả lời của Ronnie bằng cách thực hiện thành thạo để bạn có thể sử dụng nó như vậy:

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

Đối với cơ sở dữ liệu đầu tiên Aproach:

Chúng ta vẫn có thể đặt nó trong một hàm tạo, bằng cách ghi đè Mẫu ContextName.Context.tt theo cách này:

<#=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; là sự thay đổi lớn.

Đầu ra được tạo là thế này:

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

Nếu bạn thay đổi Mô hình cơ sở dữ liệu, mẫu này sẽ ở lại, nhưng lớp thực tế sẽ được cập nhật.


Có cách nào chúng ta có thể chỉ định thời gian chờ trong Mẫu bằng cách sử dụng một số tệp cấu hình.?
shas

1
không chắc chắn, nếu có thứ gì đó tích hợp (tôi không thể tìm thấy thứ gì đó). Nhưng thay vì mã hóa 180, bạn có thể sử dụng System.Configuration.ConfigurationManager.AppSettings["keyname"]@shas
Christian Gollhardt

7

Tương tự như các câu trả lời khác, nhưng là một phương pháp mở rộng:

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

và làm thế nào để tôi gọi phương thức mở rộng này?
Wanderson López

1

Tôi vừa gặp vấn đề này và giải quyết nó bằng cách cập nhật tệp cấu hình ứng dụng của tôi. Đối với kết nối được đề cập, chỉ định "Hết thời gian kết nối = 60" (Tôi đang sử dụng phiên bản khung thực thể 5.0.0.0)

Cài đặt ConnectionTimeout


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.