2009-05-26 47 views
6

Thực tiễn tốt nhất cho các kết nối SQL là gì?Quản lý các kết nối SQL Server

Hiện nay tôi đang sử dụng như sau:

using (SqlConnection sqlConn = new SqlConnection(CONNECTIONSTRING)) 
{ 
    sqlConn.Open(); 
    // DB CODE GOES HERE 
} 

Tôi đã đọc rằng đây là một cách rất hiệu quả của việc kết nối SQL. Theo mặc định, việc gộp nhóm SQL đang hoạt động, vì vậy làm thế nào tôi hiểu nó là khi mã using kết thúc đối tượng SqlConnection được đóng và xử lý nhưng kết nối thực sự với DB được đặt trong nhóm kết nối SQL. Tôi có sai về điều này không?

Trả lời

13

Đó là hầu hết trong số đó. Một số điểm bổ sung cần xem xét:

  • Bạn nhận được chuỗi kết nối ở đâu? Bạn không muốn mã hóa cứng khắp nơi và bạn có thể cần phải bảo mật nó.
  • Bạn thường có các đối tượng khác để tạo ra cũng trước khi bạn thực sự sử dụng kết nối (SqlCommand, SqlParameter, DataSet, SqlDataAdapter), và bạn muốn chờ đợi càng lâu càng tốt để mở kết nối. Mẫu đầy đủ cần phải tính đến điều đó.
  • Bạn muốn đảm bảo quyền truy cập cơ sở dữ liệu của bạn bị buộc vào lớp hoặc lắp ráp lớp dữ liệu riêng. Vì vậy, một điều phổ biến cần làm là diễn tả điều này dưới dạng gọi hàm riêng tư:

.

private static string connectionString = "load from encrypted config file"; 
private SqlConnection getConnection() 
{ 
    return new SqlConnection(connectionString); 
} 

Và sau đó viết mẫu của bạn như thế này:

using (SqlConnection sqlConn = getConnection()) 
{ 
    // create command and add parameters 

    // open the connection 
    sqlConn.Open(); 

    // run the command 
} 

mẫu Đó chỉ có thể tồn tại trong lớp truy cập dữ liệu của bạn. Một cách khác là đánh dấu nó internal và trải rộng lớp dữ liệu trên toàn bộ hội đồng. Điều chính là việc tách biệt mã cơ sở dữ liệu của bạn được thực thi nghiêm ngặt.

Một triển khai thực có thể trông như thế này:

public IEnumerable<IDataRecord> GetSomeData(string filter) 
{ 
    string sql = "SELECT * FROM [SomeTable] WHERE [SomeColumn] LIKE @Filter + '%'"; 

    using (SqlConnection cn = getConnection()) 
    using (SqlCommand cmd = new SqlCommand(sql, cn)) 
    { 
     cmd.Parameters.Add("@Filter", SqlDbType.NVarChar, 255).Value = filter; 
     cn.Open(); 

     using (IDataReader rdr = cmd.ExecuteReader()) 
     { 
      while (rdr.Read()) 
      { 
       yield return (IDataRecord)rdr; 
      } 
     } 
    } 
} 

Chú ý rằng tôi cũng đã có thể "ngăn xếp" việc tạo ra các cncmd đối tượng, và do đó làm giảm làm tổ và chỉ tạo một khối phạm vi.

Cuối cùng, hãy thận trọng khi sử dụng mã yield return trong mẫu cụ thể này. Nếu bạn gọi phương thức và không hoàn thành DataBinding hoặc sử dụng khác ngay lập tức, nó có thể giữ kết nối mở trong một thời gian dài. Một ví dụ về điều này là sử dụng nó để thiết lập một nguồn dữ liệu trong sự kiện Load của một trang ASP.NET. Vì sự kiện ràng buộc dữ liệu thực sự sẽ không xảy ra cho đến sau này, bạn có thể giữ kết nối mở lâu hơn nhiều so với mức cần thiết.

+0

điểm 1: Tôi lưu trữ các chuỗi kết nối của mình trong phần của ứng dụng/web.config Điểm 2: Đây có phải là điều tôi nên lo lắng không. Tôi thường làm SqlConnection, sau đó mở nó, sau đó tạo sqlCommand của tôi và sau đó lấy nếu từ đó. Điểm 3: Chúng tôi thực hiện tất cả truy cập DB từ một lớp lib. Tôi không thích làm DB truy cập hình thức ứng dụng cốt lõi. Có đáng để tôi tạo phương thức getConnection không? – Neale

+0

Vì bạn sử dụng một lớp lib cho tất cả truy cập db, nó là một điều đơn giản để làm cho phần chuỗi kết nối của tệp .config của lớp lib chứ không phải tệp .config sẽ là toàn cục cho toàn bộ ứng dụng. Điều này sẽ đủ tốt để thực thi việc tách lớp dữ liệu sạch, nhưng đồng thời cũng không có lý do gì để đưa phương thức này ra công khai. Điều đó sẽ giải quyết điểm 1 & 3. Đối với điểm 2, nó có thể không làm tổn thương bất cứ điều gì để có nó mở cho một hoặc hai dòng phụ, nhưng nó không giúp đỡ một trong hai. Tôi đang chỉnh sửa bằng một lý do khác mà bạn có thể muốn thực hiện theo cách đó. –

+0

Ví dụ về 'lợi nhuận của bạn' hơi gây hiểu nhầm. Một hàm được xây dựng xung quanh 'return yield' không bắt đầu thực thi cho đến lần gọi đầu tiên của' MoveNext() 'trên' IEnumerator'. Vì vậy, ngay cả khi bạn gọi hàm, kết nối sẽ không được mở cho đến khi bạn bắt đầu lặp lại kết quả. –

1

Hiểu biết của bạn về việc sử dụng là chính xác và phương pháp sử dụng đó là cách được khuyến nghị làm như vậy. Bạn cũng có thể gọi gần mã của bạn.

+1

Cảm ơn. Cách mà tôi hiểu rằng khi "sử dụng" được hoàn thành và điều đó gọi SqlConnection.Dispose(); mà Ultimatly gọi SqlConnection.Close() – Neale

+0

sự hiểu biết của bạn về "sử dụng" là chính xác là tốt. –

+0

@Neale - Yea, SqlConnection.Dispose() sẽ gọi Close nếu nó được yêu cầu. Nếu kết nối đã được đóng, nó chỉ cần giải phóng xử lý trở lại nhà cung cấp ado.net, sau đó tự do đưa nó vào một hồ bơi hoặc thực sự đóng nó lại. –

2

Thư viện Patterns and Practices của Microsoft là một cách tiếp cận tuyệt vời để xử lý kết nối cơ sở dữ liệu. Các thư viện đóng gói hầu hết các cơ chế liên quan đến việc mở một kết nối, do đó sẽ làm cho cuộc sống của bạn dễ dàng hơn.

0

Ngoài ra: Mở muộn, đóng sớm.

Không mở kết nối cho đến khi không còn bước nào nữa trước khi gọi cơ sở dữ liệu. Và đóng kết nối ngay khi bạn hoàn tất.

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