2009-05-22 42 views
5

Có thực hành tốt để có một đối tượng SqlConnection được chia sẻ trong một ứng dụng .NET để sử dụng cho tất cả các kết nối cơ sở dữ liệu của bạn hay bạn nên có một riêng biệt mỗi khi bạn truy nhập cơ sở dữ liệu?SqlConnection được chia sẻ

Tôi hiện đang chia sẻ và dường như sắp gặp sự cố đột ngột. Có vẻ như tôi không thể sử dụng một chia sẻ khi tôi cần sử dụng chế độ xác thực SQL thay vì chế độ xác thực của Windows. Tôi vừa thử lần đầu tiên sử dụng xác thực SQL và nó đã cho tôi lỗi này khi tôi thử sử dụng cùng một kết nối lần thứ hai:

Đã có một DataReader mở được liên kết với Lệnh này phải đóng trước.

Trả lời

4

Bạn nên có một riêng biệt thực sự. Việc sử dụng lại các kết nối được xử lý với connection pooling. Vấn đề thứ hai như những người khác đã nói có thể có thể được giải quyết bằng cách kích hoạt MARS.

0

Nếu bạn đang sử dụng SQL Server 2000, this có thể trả lời câu hỏi của bạn.

Câu trả lời chiến thắng dường như là "Điều này là do thay đổi trong cài đặt mặc định cho MAR. Nó được sử dụng theo mặc định và chúng tôi đã thay đổi thành tắt theo mặc định bài RC1. thêm nó trở lại (thêm MultipleActiveResultSets = True để kết nối chuỗi). "

1

Rất nhiều điều này có thể là dup from here; trong ngắn hạn, giữ cho các kết nối ngắn ngủi và địa phương trong hầu hết các trường hợp. Hãy đọc lại trình đọc dữ liệu; có lẽ bật MARS?

1

Trong khi đối với một chuỗi đơn, nó có thể hoạt động tốt hơn khi sử dụng một đối tượng SqlConnection duy nhất, nó yêu cầu tài nguyên quý giá là máy chủ cơ sở dữ liệu của bạn bằng cách treo vào kết nối và do đó tài nguyên máy chủ db dài hơn.

Tốt hơn là khởi tạo SqlConnection trong một khoảng thời gian ngắn nhất có thể. Kết nối tổng hợp giảm thiểu hầu hết các chi phí của việc thiết lập kết nối, và đảm bảo sử dụng hiệu quả nhất các tài nguyên cơ sở dữ liệu.

3

Lỗi đó hoàn toàn không liên quan đến xác thực. Bạn đang tái sử dụng một kết nối từ giữa trước khi bạn đóng SqlDataReader của bạn trả về từ một ExecuteReader(). Điều này bị cấm. Bạn phải kiểm tra mã của bạn và loại bỏ vấn đề của bạn. Có những lựa chọn thay thế để sử dụng MARS (multiple active record sets) nhưng tôi sẽ mạnh mẽ không khuyến khích điều đó.

Sử dụng nhiều kết nối trong ứng dụng của bạn có thể còn tồi tệ hơn vì dường như bạn không biết kết nối đang được sử dụng và khi nào, khi bạn sử dụng kết nối riêng biệt, bạn sẽ gặp phải sự cố nhất quán về giao dịch.

+0

Nếu bạn đang nói "không sử dụng MARS" - bạn có lý do cụ thể nào không? Out of curiosity ... –

+0

http://blogs.msdn.com/sqlnativeclient/archive/2006/09/27/774290.aspx thảo luận về một số âm bản để sử dụng MARS – RichardOD

+2

Mô hình cách ly giao dịch của MARS không đầy đủ, như trong không hoàn toàn được xác định theo lý thuyết. Kết quả là máy chủ có thể bị 'nhầm lẫn', vì liên kết được đăng bởi Richard thừa nhận. Cái 'nhầm lẫn' đó thường có nghĩa là số lượng tương tác có thể quá lớn và không phải tất cả các đường dẫn mã trong máy chủ đều được kiểm tra và xác thực. –

2

Vấn đề của bạn là bạn đang cố sử dụng kết nối hiện đang được SqlDataReader sử dụng. Bạn không thể làm điều đó. Khi bạn sử dụng SqlDataReader, bạn phải đóng nó trước khi sử dụng lại kết nối đang được tiêu thụ. Tôi đề nghị bạn tạo một kết nối khác nhau mỗi khi bạn truy cập vào DB (bất cứ lúc nào, không chỉ với SqlDataReaders). Nếu bạn đã bật tính năng tổng hợp, thì chính khung công tác (hoặc là SqlServer?) Sẽ tái sử dụng các kết nối khi có thể.

Nếu bạn cần truy cập DB tuần tự, giả sử bạn chọn, sau đó chọn khác, sau đó cập nhật, bạn có thể sử dụng lại kết nối (ý tôi là, cùng một cá thể SqlConnection), nhưng nếu bạn cần truy cập DB trong khi đọc từ một SqlDataReader, sau đó bạn sẽ cần 2 kết nối khác nhau.

Tất nhiên bạn phải ghi nhớ các vấn đề tương tranh.Nếu bạn sử dụng giao dịch thì một số bản ghi có thể bị khóa trong một số hoạt động nhất định và khi bạn sử dụng SqlDataReader song song với các truy vấn khác, bạn nên đặt mức cách ly thành mức không gây rối với phần còn lại của truy vấn.

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