Mở / đóng, mở S SConnConnection hay giữ mở?


121

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 thức này mở / đóng kết nối SQL khi được gọi:

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

        // ...

        connection.Close();
    }
}

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

//pass the connection object into the method
public static void DoSomething(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 thức (a) hay phương thức (b)? Tôi đã đọc trên một câu hỏi stackoverflow khác rằng kết nối đã lưu hiệu suất cho tôi, tôi hoàn toàn không phải bận tâm ...

Tái bút Đây là một ứng dụng ASP.NET - các kết nối chỉ tồn tại trong một yêu cầu web. Không phải là một ứng dụng hoặc dịch vụ win.


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

1
Một chi tiết còn thiếu là phương pháp này là một phần của yêu cầu trang. Đây có phải là phương pháp duy nhất được gọi hay không, như tôi đã giả sử trong phản hồi của mình, một trong nhiều phương thức được gọi trong trang reqest, nó ảnh hưởng đến câu trả lời nào là đúng;)
David Mårtensson

David - RẤT NHIỀU phương thức như thế này đang được gọi :)
Alex

1
Trường hợp Một chương trình thiếu niềm tin vào Vứt bỏ: xem stackoverflow.com/questions/1195829/... và ví dụ trên MSDN msdn.microsoft.com/en-us/library/...
user2864740

Câu trả lời:


82

Bám sát tùy chọn a .

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


37
IMHO - anh ấy thậm chí không nên đóng. các xử lý sẽ làm điều đó.
Royi Namir

2
@RoyiNamir Tôi thích 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

27
@edhedges Sử dụng cả "sử dụng" và Đóng () cuối cùng sẽ chỉ gây nhầm lẫn cho người mới. Họ sẽ không hiểu mục đích của việc sử dụng "sử dụng". Đừng sử dụng "Đóng" thay vào đó hãy dạy 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 vào các phần khác của mã.
Luis Perez

1
Có nên / gọi "Open ()" không? Tôi hiện đang sử dụng nó như thế này: bằng cách sử dụng (var Conn = GetConnection ()) {} công khai SqlConnection GetConnection () {trả về SqlConnection mới (_connectionString); }
ganders

79

Sử dụng Phương pháp (a), mọi lúc. Khi bạn bắt đầu nhân rộng ứng dụng của mình, logic liên quan đến trạng thái sẽ trở thành nỗi đau thực sự nếu bạn không làm vậy.

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


33

Luôn đóng các kết nối ngay khi bạn hoàn thành với chúng, để chúng kết nối cơ sở dữ liệu bên dưới có thể quay lại nhóm và có sẵn cho những người gọi khác. Kết nối tổng hợp được tối ưu hóa khá tốt, do đó không có hình phạt đáng chú ý nào khi làm như vậy. Lời khuyên về cơ bản giống như đối với các giao dịch - hãy giữ chúng ngắn gọn và gần gũi khi bạn hoàn thành.

Sẽ phức tạp hơn nếu bạn gặp phải các 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ó sau khi giao dịch được thực hiện.

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


Bạn không nên bình thường mở và đóng một 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. Đó là những gì tôi đã học ít nhất;) Mở và đóng chi phí thời gian.
David Mårtensson

8
@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 được sử dụng trước đó. Chi phí liên quan đến việc này là không quan trọng, và ngoài ra, cố gắng "tự làm" có nghĩa là bạn phải đảm 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.
Jamie Treworgy

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

@David Martensson "Một lần cho mỗi trang" là quá đơn giản. Bạn đúng rằng nếu bạn có một số lệnh cơ sở dữ liệu để thực thi lần lượt từng lệnh khác, bạn có thể giữ kết nối mở trong khi bạn thực hiện chúng. Sẽ có một chi phí nhỏ nếu bạn đóng và mở lại - kết nối sẽ đi vào nhóm và được truy xuất từ ​​đó một lát sau.
Bê tông Gannet

1
@David Martensson Nhưng không bao giờ giữ kết nối nhàn rỗi. Nếu bạn đang chờ đợi một hành động từ người dùng hoặc cho bất cứ điều gì khác, hãy đóng nó. Nếu nghi ngờ, hãy đóng nó lại. Bạn mở càng muộn càng tốt với hy vọng ai đó đã kết thúc với một kết nối và gộp nó lại. Sau đó, bạn trả lại sự ủng hộ - đóng cửa sớm nhất có thể.
Bê tông Gannet

13

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

Nếu bạn gặp khó khăn khi tin rằng việc tổng hợp thực sự sẽ nhanh hơn, thì hãy thử điều này:

Thêm vào đây ở đâ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 bó rất mở nhanh.

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


9

Có sự phân biệt giữa các 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ó các giới hạn đối với các kết nối song song trên máy chủ db - tính đến điều đó là cần thiết để làm cho các kết nối của bạn rất ngắn.

Nhóm kết nối 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à ngay lập tức đóng chúng.


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 kết nối vật lý cơ bản.
Bê tông Gannet

Thật không may, ngay lập tức rõ ràng rằng điều này đã được thực hiện hoàn toàn, nhưng tài liệu xây dựng trên đó. docs.microsoft.com/en-us/dotnet/framework/data/adonet/iêu
Austin Salgat

2

Thông thường, bạn nên giữ một kết nối cho mỗi giao dịch (không tính toán song song)

ví dụ: khi người dùng thực hiện hành động tính phí, ứng dụng của bạn cần tìm số dư của người dùng trước và cập nhật nó, họ nên sử dụng cùng một kết nối.

Ngay cả khi ado.net có nhóm kết nối, chi phí kết nối rất thấp, nhưng kết nối sử dụng lại là lựa chọn tốt hơn.

Tại sao không chỉ giữ một kết nối trong ứng dụng

Bởi vì kết nối bị chặn khi bạn thực hiện một số truy vấn hoặc lệnh, vì vậy điều đó có nghĩa là ứng dụng của bạn chỉ thực hiện một thao tác db vào thời gian, hiệu suất của nó kém như thế nào.

Một vấn đề nữa là ứng dụng của bạn sẽ luôn có kết nối mặc dù người dùng của bạn chỉ mở nhưng không có hoạt động. Nếu có nhiều người dùng mở ứng dụng của bạn, máy chủ db sẽ sớm mất tất cả nguồn kết nối trong khi người dùng của bạn không làm như vậy bất cứ điều gì

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.