2012-04-17 28 views
6

Tôi có một ứng dụng web khá lớn bằng cách sử dụng LINQ-TO-SQL đang chạy trong Azure và tôi gặp phải lỗi Transient từ SQL-Azure và do đó cần triển khai thử lại. Tôi nhận thức được Transient Fault Handling Framework và một số trang web cung cấp cho ví dụ làm thế nào để sử dụng nó, nhưng có vẻ như bạn phải quấn mỗi một trong các truy vấn LINQ của bạn trong một cái gì đó tương tự như sau:Thử lại Logic cho LINQ-TO-SQL trên SQL Azure - Triển khai hiệu quả?

RetryPolicy retry = new RetryPolicy<MyRetryStrategy>(5, TimeSpan.FromSeconds(5)); 
Result = retry.ExecuteAction(() => 
{ 
    … LINQ query here... 
}); 

Với hàng trăm các truy vấn LINQ trong lớp dữ liệu của tôi, điều này có vẻ thực sự lộn xộn, cộng với thực tế là nhiều lần truy vấn không thực sự được thực hiện cho đến khi kết quả được liệt kê. Ví dụ, hầu hết các hàm của tôi trong lớp dữ liệu của tôi trả lại một IQueryable <> lên đến lớp nghiệp vụ, (làm cho chúng linh hoạt hơn việc trả về một Danh sách). Vì vậy, điều đó có nghĩa là bạn phải xả rác lớp logic kinh doanh của bạn với cơ sở dữ liệu thử lại logic - xấu xí. Vì vậy, tôi đoán để giữ logic thử lại trong lớp dữ liệu, tôi sẽ phải đặt .ToList() trên tất cả các truy vấn của tôi để chúng được thực thi ngay tại đó, và không phải trong lớp ở trên.

Tôi thực sự muốn có một cách để thực hiện thử lại logic trong một số lớp cơ sở và không phải thay đổi tất cả các truy vấn của tôi. Có vẻ như EF cũng sẽ có vấn đề này.

Câu trả lời thực sự là thử và nói với nhóm SQL-Azure để thực hiện tự động thử lại, vì vậy chúng tôi không phải lo lắng về điều đó trong mã của chúng tôi?

Trả lời

0

Tôi không biết giải pháp tốt vì LINQ to SQL không cho phép chúng tôi chặn truy vấn. Nhưng một trình mã hóa nhỏ có thể giúp. Giống như (pseudo code):

public Result QueryWithRetry(IQueryable query) 
{ 
     RetryPolicy retry = new RetryPolicy<MyRetryStrategy>(5, TimeSpan.FromSeconds(5)); 
    (() => 
    { 
     return retry.ExecuteAction(query); 
    } 
} 

Bây giờ nó là một chút dễ dàng hơn để gọi phương pháp này:

Result = QueryWithRetry (... LINQ truy vấn ở đây ...);

Tuy nhiên, vẫn cần phải sửa đổi mã của bạn và thay đổi mọi truy vấn.

Trân trọng,

Ming Xu.

+0

Điều đó sẽ giúp ích một chút, nhưng tôi vẫn không phải lo lắng về các truy vấn không thực sự thực thi cho đến sau này trong mã mà chúng được liệt kê không? Vì vậy, tôi sẽ phải thực sự điều tra từng truy vấn và tìm ra nơi mà cơ sở dữ liệu thực sự được gọi. – PeteShack

+0

Rất tiếc, tôi không thể hiểu rõ bạn. Bạn có nghĩa là bạn đang lo lắng nếu có điều gì đó không ổn, sẽ khó tìm ra nguồn gốc của vấn đề bởi vì các truy vấn được bao bọc bên trong một khuôn khổ thử lại? Trong trường hợp này, tôi muốn đề nghị bạn thiết lập một điểm ngắt trên retry.ExecuteAction và bước qua mã. –

+0

Không, ý tôi là thêm logic thử lại vào một ứng dụng hiện có với hàng trăm truy vấn sẽ là một nhiệm vụ khó khăn - chủ yếu là do cuộc gọi cơ sở dữ liệu không nhất thiết xảy ra trong truy vấn LINQ-to-sql trong lớp dữ liệu. Việc thực hiện truy vấn có thể bị trì hoãn cho đến khi IQueryable thực sự được liệt kê - điều này có thể xảy ra trong lớp nghiệp vụ. Có vẻ như không phải là một giải pháp sạch cho vấn đề này. – PeteShack

1

Sau khi cần triển khai một cái gì đó như thế này, tôi đã tiếp tục và làm cho nó trở thành một thư viện: https://github.com/daveaglick/LinqToSqlRetry (MIT được cấp phép và có sẵn trên NuGet).

Bạn có thể thử lại SubmitChanges() cuộc gọi bằng cách viết SubmitChangesRetry() thay vì:

using(var context = new MyDbContext()) 
{ 
    context.Items.InsertOnSubmit(new Item { Name = "ABC" }); 
    context.SubmitChangesRetry(); 
} 

Bạn cũng có thể thử truy vấn bằng cách sử dụng phương pháp Retry() mở rộng:

using(var context = new MyDbContext()) 
{ 
    int count = context.Items.Where(x => x.Name == "ABC").Retry().Count(); 
} 

Logic retry cụ thể là kiểm soát bởi chính sách. Dưới mui xe, cơ chế retry trông giống như:

int retryCount = 0; 
while (true) 
{ 
    try 
    { 
     return func(); 
    } 
    catch (Exception ex) 
    { 
     TimeSpan? interval = retryPolicy.ShouldRetry(retryCount, ex); 
     if (!interval.HasValue) 
     { 
      throw; 
     } 
     Thread.Sleep(interval.Value); 
    } 
    retryCount++; 
} 

Hiểu rằng các chức năng trong các cuộc gọi đến func() và đối tượng retryPolicy được cung cấp dựa trên việc sử dụng. Điều này chỉ cung cấp cho bạn một ý tưởng những gì đang xảy ra trong vòng lặp thử lại. Chỉ cần nhìn vào kho lưu trữ để biết thêm thông tin.

Các vấn đề liên quan