Thời gian chờ khung thực thể


324

Tôi đang hết thời gian sử dụng Entity Framework (EF) khi sử dụng chức năng nhập mất hơn 30 giây để hoàn thành. Tôi đã thử những điều sau đây và không thể giải quyết vấn đề này:

Tôi đã thêm vào Default Command Timeout=300000chuỗi kết nối trong tệp App.Config trong dự án có tệp EDMX như được đề xuất ở đây .

Đây là chuỗi kết nối của tôi trông như thế nào:

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

Tôi đã cố gắng thiết lập CommandTimeout trong kho lưu trữ của mình trực tiếp như vậy:

private TrekEntities context = new TrekEntities();

public IEnumerable<TrekMatches> GetKirksFriends()
{
    this.context.CommandTimeout = 180;
    return this.context.GetKirksFriends();
}

Tôi có thể làm gì khác để đưa EF hết thời gian? Điều này chỉ xảy ra đối với các bộ dữ liệu rất lớn. Tất cả mọi thứ hoạt động tốt với bộ dữ liệu nhỏ.

Đây là một trong những lỗi tôi gặp phải:

System.Data.EntityCommandExecutException: Xảy ra lỗi trong khi thực hiện định nghĩa lệnh. Xem ngoại lệ bên trong để biết chi tiết. ---> System.Data.SqlClient.SqlException: Hết hạn. Khoảng thời gian chờ đã trôi qua trước khi hoàn thành thao tác hoặc máy chủ không phản hồi.


OK - Tôi đã làm việc này và thật ngớ ngẩn những gì đã xảy ra. Tôi đã có cả chuỗi kết nối với Default Command Timeout=300000và CommandTimeout được đặt thành 180. Khi tôi xóa Default Command Timeoutchuỗi kết nối, nó đã hoạt động. Vì vậy, câu trả lời là đặt thủ công CommandTimeout trong kho lưu trữ của bạn trên đối tượng ngữ cảnh của bạn như sau:

this.context.CommandTimeout = 180;

Rõ ràng việc thiết lập các cài đặt thời gian chờ trong chuỗi kết nối không ảnh hưởng đến nó.


Xóa & quot; từ chuỗi kết nối
Brian Webster


5
@ hamlin11 Trong chuỗi kết nối EF, cần phải xác định phần nào là chuỗi kết nối và phần nào là siêu dữ liệu EF. Để lại &quot;trong chuỗi.
Chev

2
đề nghị của tôi là trước khi bạn tăng thời gian chờ để điều tra trước để xem tại sao EF hết thời gian. Trong trường hợp của chúng tôi, chúng tôi nhận ra rằng chúng tôi cần thêm NONCLUSTEREDchỉ mục vào một số bảng, điều này đã giải quyết vấn đề hết thời gian cho chúng tôi.
zulucoda

Tôi đang làm việc với bộ phận hỗ trợ của MS về vấn đề hết thời gian SQL - đây là khi DB được lưu trữ trong SQL Azure. Tôi được thông báo rằng tất cả các dịch vụ Azure PaaS (trang web PaaS và SQL Azure, v.v.) có thời gian chờ phổ biến là 230 giây và điều này luôn được ưu tiên, ngay cả khi bạn đặt thời gian chờ thủ công. Điều này là để bảo vệ tài nguyên của cơ sở hạ tầng PaaS nhiều bên.
Ian Robertson

Câu trả lời:


552

Có một lỗi đã biết với việc chỉ định thời gian chờ lệnh mặc định trong chuỗi kết nối EF.

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

Xóa giá trị khỏi chuỗi kết nối và đặt nó trên chính đối tượng bối cảnh dữ liệu. Điều này sẽ hoạt động nếu bạn loại bỏ giá trị xung đột khỏi chuỗi kết nối.

Thực thể khung cốt lõi 1.0:

this.context.Database.SetCommandTimeout(180);

Khung thực thể 6:

this.context.Database.CommandTimeout = 180;

Khung thực thể 5:

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

Thực thể khung 4 trở xuống:

this.context.CommandTimeout = 180;

5
Làm thế nào tôi có thể đạt được điều này bằng cách sử dụng edmx?
iroel

2
Phiên bản EntityFramework này được sửa trong phiên bản nào? Tôi không thể tìm thấy lỗi EF cho nó.
rudimenter

7
Tôi không tin rằng đây là một lỗi, mà là do thiết kế, xem phần chú thích ở đây liên kết
Mick P

3
Vì một số cài đặt được tính bằng ms và một số tính bằng s, tôi đã tra cứu nó ở đây , CommandTimeout chỉ trong vài giây.
JabberwockyDecompiler

6
Trong Entity Framework 7, bạn có thể thiết lập điều này trong hàm tạo của DbContext / IdentityDbContext:this.Database.SetCommandTimeout(180);
Thomas Hagström

101

Nếu bạn đang sử dụng DbContext, hãy sử dụng hàm tạo sau để đặt thời gian chờ lệnh:

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

3
@ErickPetru, vì vậy bạn có thể dễ dàng thay đổi nó thành một số phút khác nhau :), tôi cũng sẽ không quá ngạc nhiên nếu trình biên dịch tối ưu hóa phép nhân đó!
Joel Verhagen

2
@JoelVerhagen, đừng ngạc nhiên. Dưới đây là một lời giải thích tốt về thời điểm tối ưu hóa tự động xảy ra: stackoverflow.com/questions/160848/ . Trong trường hợp này, tôi cho rằng điều đó thậm chí xảy ra (vì chúng là hai giá trị theo nghĩa đen), nhưng thực lòng tôi nghĩ rằng mã này là loại lạ theo cách này.
Erick Petrucelli

33
meh ... trẻ em đang đói ... ai quan tâm đến 1 * 60?
Timmerz

9
@ErikPetru, đây thực sự là một thực tế rất phổ biến và làm cho mã dễ đọc hơn.
Calvin

Cách tốt nhất để xử lý điều này là do DbContextlớp dẫn xuất của tôi được tạo tự động từ một edmxtệp?
Matt Burland

41

Nếu bạn đang sử dụng DbContextvà EF v6 +, bạn có thể sử dụng:

this.context.Database.CommandTimeout = 180;

13

Thông thường tôi xử lý các hoạt động của mình trong một giao dịch . Như tôi đã trải nghiệm, việc đặt thời gian chờ lệnh bối cảnh là không đủ, nhưng giao dịch cần một hàm tạo với tham số hết thời gian chờ. Tôi đã phải đặt cả hai giá trị thời gian để nó hoạt động đúng.

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

Khi kết thúc chức năng, tôi đặt lại thời gian chờ lệnh về giá trị trước đó.

Sử dụng EF6


Không phải là một cách tiếp cận tốt cả. Tôi đã từng thêm rất nhiều phạm vi giao dịch và nó trở thành cơn ác mộng đối với tôi trong một dự án. Cuối cùng đã thay thế tất cả phạm vi giao dịch bằng một SAVEChanges () trong EF 6+. Kiểm tra coderwall.com/p/jnniww/
Moons

Câu trả lời này nên có phiếu bầu cao hơn. Tôi đã thử tất cả các cách khác nhau để tăng thời gian chờ nhưng chỉ khi tôi đặt thời gian chờ lệnh BST bối cảnh và phạm vi Giao dịch thì nó mới hoạt động.
Gang

3

Tôi biết đây là chủ đề rất cũ đang chạy, nhưng vẫn chưa sửa lỗi này. Đối với những người sử dụng tự động tạo DbContextcó thể sử dụng mã sau đây để đặt thời gian chờ theo cách thủ công.

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

Nếu bạn đang sử dụng Entity Framework như tôi, bạn nên xác định Hết giờ trên lớp Khởi động như sau:

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

1

Đây là những gì tôi đã tài trợ. Có lẽ nó sẽ giúp cho ai đó:

Vì vậy, ở đây chúng tôi đi:

Nếu bạn sử dụng LINQ với EF tìm kiếm một số yếu tố chính xác có trong danh sách như thế này:

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

mọi thứ đều ổn cho đến khi IdList chứa nhiều hơn một Id.

Vấn đề về thời gian chờ của người nổi tiếng xuất hiện nếu danh sách chỉ chứa một Id. Để giải quyết vấn đề, hãy sử dụng if condition để kiểm tra số lượng id trong IdList.

Thí dụ:

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

Giải trình:

Đơn giản chỉ cần thử sử dụng Sql Profiler và kiểm tra câu lệnh Chọn được tạo bởi Entity frameeork. Giáo dục

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.