2010-12-14 28 views
82

Tôi có logic nghiệp vụ của mình được triển khai trong các lớp tĩnh đơn giản với các phương thức tĩnh. Mỗi phương pháp mở/đóng kết nối SQL khi gọi:"mở/đóng" SqlConnection hoặc tiếp tục mở?

public static void AddSomething(string something) 
{ 
    using (SqlConnection connection = new SqlConnection("...")) 
    { 
     connection.Open(); 

     // ... 

     connection.Close(); 
    } 
} 

Nhưng tôi nghĩ rằng tránh mở và đóng một kết nối tiết kiệm hiệu suất. Tôi đã thực hiện một số xét nghiệm loooong thời gian trước đây với OleDbConnection lớp (không chắc chắn về SqlConnection), và nó chắc chắn giúp làm việc như thế này (như xa như tôi nhớ):

//pass the connection object into the method 
public static void AddSomething(string something, SqlConnection connection) 
{ 
    bool openConn = (connection.State == ConnectionState.Open); 
    if (!openConn) 
    { 
     connection.Open(); 
    } 

    // .... 

    if (openConn) 
    { 
     connection.Close(); 
    } 
} 

Vì vậy, câu hỏi là - Tôi nên chọn phương pháp (a) hoặc phương pháp (b)? Tôi đọc trên một câu hỏi stackoverflow khác mà kết nối tổng hợp hiệu suất lưu cho tôi, tôi không phải lo lắng chút nào ...

PS. Đó là một ứng dụng ASP.NET - các kết nối tồn tại chỉ trong một yêu cầu web. Không phải là một ứng dụng hoặc dịch vụ giành chiến thắng.

+1

Chỉ cần một lời khuyên: Sử dụng sự kiện 'DbConnection.StateChange' để theo dõi các thay đổi về thay đổi trạng thái của kết nối (và có thể lưu trữ cục bộ) thay vì kiểm tra thuộc tính' DbConnection.State' trực tiếp. Nó sẽ giúp bạn tiết kiệm chi phí hiệu suất. – decyclone

+1

Một chi tiết bị thiếu là cách thức này là một phần của yêu cầu trang. Nó là phương pháp duy nhất được gọi là hoặc là nó, như tôi giả định trong phản ứng của tôi, một trong nhiều phương pháp thats được gọi trong một reqest trang, nó ảnh hưởng đến câu trả lời là đúng;) –

+0

David - LOTS của phương pháp như thế này đang được gọi là :) – Alex

Trả lời

59

Gắn vào tùy chọn.

Kết nối tổng hợp là bạn của bạn.

+23

IMHO - anh ấy thậm chí không nên đóng cửa. việc vứt bỏ sẽ làm điều đó. –

+2

@RoyiNamir Tôi giống như cuộc gọi để đóng kết nối. Đặc biệt là cho người mới bắt đầu và người mới đến một cơ sở mã. Nó rõ ràng và dễ đọc hơn. – edhedges

+10

@edhedges Sử dụng cả "sử dụng" và Close() cuối cùng sẽ chỉ gây nhầm lẫn cho người mới đến. Họ sẽ không hiểu mục đích của việc sử dụng "sử dụng". Không sử dụng "Đóng" thay vì dạy cho họ mục đích "sử dụng". Để họ có thể học tốt hơn và áp dụng những gì họ học được vào các phần khác của mã. –

25

Luôn đóng các kết nối ngay sau khi bạn đã hoàn tất với chúng, do đó chúng có thể quay trở lại hồ bơi và có sẵn cho những người gọi khác. Kết nối tổng hợp là khá tốt tối ưu hóa, do đó, không có hình phạt đáng chú ý để làm như vậy. Lời khuyên về cơ bản giống như đối với các giao dịch - giữ chúng ngắn gọn và gần gũi khi bạn hoàn tất. Sẽ phức tạp hơn nếu bạn gặp sự cố MSDTC bằng cách sử dụng một giao dịch xung quanh mã sử dụng nhiều kết nối, trong trường hợp đó bạn thực sự phải chia sẻ đối tượng kết nối và chỉ đóng nó khi giao dịch được thực hiện với .

Tuy nhiên bạn đang làm mọi thứ bằng tay tại đây, vì vậy, bạn có thể muốn điều tra các công cụ quản lý kết nối cho bạn, như DataSets, LINQ to SQL, Entity Framework hoặc NHibernate.

+0

Bạn không nên bình thường mở và đóng kết nối trong mọi cuộc gọi phương thức, chỉ một lần cho mỗi yêu cầu trang. Thats những gì tôi đã học được ít nhất;) Mở và đóng cửa chi phí thời gian. –

+7

@David Martensson - các kết nối không thực sự được mở và đóng khi bạn gọi SqlConnection.Open. ASP.NET tái chế các kết nối hoạt động từ nhóm khi chuỗi kết nối khớp với chuỗi kết nối đã sử dụng trước đây. Chi phí liên quan đến điều này là không quan trọng, và bổ sung, cố gắng "tự làm" nghĩa là bạn phải thừa nhận tất cả các nhiệm vụ quản lý để đảm bảo kết nối vẫn hoạt động cho mỗi lần sử dụng tiếp theo, điều này làm tăng thêm sự phức tạp và chi phí. Với kết nối tổng hợp, thực hành tốt nhất là mở và đóng nó cho mọi lần sử dụng. –

+2

Với tất cả sự tôn trọng của tôi, câu trả lời "Luôn luôn đóng kết nối" không phù hợp với câu hỏi rất tốt ... Tôi đóng chúng lại. Câu hỏi đặt ra là - khi nào. – Alex

66

Sử dụng phương pháp (a), mọi lúc. Khi bạn bắt đầu mở rộng quy mô ứng dụng của mình, logic giao dịch với nhà nước sẽ trở thành nỗi đau thực sự nếu bạn không thực hiện.

Kết nối tổng hợp thực hiện những gì nó nói trên tin. Chỉ cần nghĩ về những gì sẽ xảy ra khi ứng dụng mở rộng quy mô và sẽ khó khăn như thế nào để quản lý trạng thái mở/đóng kết nối theo cách thủ công. Các hồ bơi kết nối hiện một công việc tốt của tự động xử lý này. Nếu bạn lo lắng về hiệu suất suy nghĩ về một số loại cơ chế bộ nhớ cache để không có gì bị chặn.

+3

Tôi sẽ upvote bạn +50 nếu tôi có thể :-) –

6

Có sự khác biệt giữa kết nối vật lý và logic. DbConnection là một loại kết nối hợp lý và nó sử dụng kết nối vật lý cơ bản với Oracle. Đóng/mở DbConnection không ảnh hưởng đến hiệu suất của bạn, nhưng làm cho mã của bạn sạch sẽ và ổn định - không thể rò rỉ kết nối trong trường hợp này.

Ngoài ra, bạn nên nhớ về các trường hợp khi có giới hạn cho kết nối song song trên máy chủ db - tính đến điều đó là cần thiết để kết nối của bạn rất ngắn.

Hồ bơi kết nối sẽ giải phóng bạn khỏi việc kiểm tra trạng thái kết nối - chỉ cần mở, sử dụng và đóng ngay lập tức.

+0

Có, kết nối không phải là kết nối - tức là DbConnection không phải là kết nối vật lý. DbConnection là một lớp .NET cung cấp các phương thức và thuộc tính để thao tác với kết nối vật lý cơ bản. –

10

Tuyên bố từ chối trách nhiệm: Tôi biết điều này là cũ, nhưng tôi đã tìm thấy một cách dễ dàng để chứng minh điều này, vì vậy tôi đang đặt trong hai xu giá trị của tôi.

Nếu bạn gặp sự cố tin rằng tổng hợp được thực sự sẽ nhanh hơn, sau đó cung cấp cho một thử này:

Thêm dòng sau ở đâu đó:

using System.Diagnostics; 
public static class TestExtensions 
{ 
    public static void TimedOpen(this SqlConnection conn) 
    { 
     Stopwatch sw = Stopwatch.StartNew(); 
     conn.Open(); 
     Console.WriteLine(sw.Elapsed); 
    } 
} 

Bây giờ thay thế tất cả các cuộc gọi đến Open() với TimedOpen() và chạy chương trình của bạn. Bây giờ, đối với mỗi chuỗi kết nối riêng biệt mà bạn có, cửa sổ giao diện điều khiển (đầu ra) sẽ có một lần chạy dài mở và một loạt các mở nhanh rất.

Nếu bạn muốn gắn nhãn chúng, bạn có thể thêm new StackTrace(true).GetFrame(1) + vào cuộc gọi đến WriteLine.

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