2009-06-06 22 views
6

Trong Java và C#, cả hai đều có một cái gì đó giống như System.terminate(). Nếu chương trình của tôi có các kết nối cơ sở dữ liệu mở, các trình đọc cơ sở dữ liệu và các biến lệnh cơ sở dữ liệu, và tôi chấm dứt chương trình của tôi trong một điều khoản bắt, các tài nguyên cơ sở dữ liệu vẫn còn được sử dụng không? hoặc chúng sẽ được giải phóng tự động vì toàn bộ chương trình của tôi vừa mới thoát?Nếu chương trình bàn điều khiển kết thúc, các kết nối cơ sở dữ liệu được sử dụng trong chương trình vẫn còn mở?

Thông thường, tôi nên xử lý các trường hợp như thế nào để đảm bảo tôi luôn luôn kết nối cơ sở dữ liệu miễn phí, cho dù thông qua chấm dứt chương trình bình thường hoặc chấm dứt chương trình không mong muốn? Bất kỳ thực hành tốt nào?

Trả lời

0

Trong C#, bạn sẽ kết nối thường đóng ngay sau khi sử dụng chúng, ví dụ:

using(SqlConnection connection = ...) 
{ 
    ... do something ... 
} // connection disposed/closed here 

Tuy nhiên, thông thường bạn sẽ sử dụng một hồ bơi kết nối và tất cả điều này sẽ trả về kết nối với hồ bơi. Vì vậy, quá trình của bạn sẽ vẫn có các kết nối hoạt động với máy chủ cơ sở dữ liệu.

Nếu bạn tắt sạch, hồ bơi kết nối sẽ không bị nghi ngờ, và kết nối thực sự với cơ sở dữ liệu sẽ bị đóng (bạn có thể xác minh điều này bằng cách xem các kết nối mở trên máy chủ cơ sở dữ liệu).

Nhưng có những tình huống (ví dụ: gọi Environment.FailFast) nơi ứng dụng có thể gặp sự cố mà không đóng kết nối - trong trường hợp này, cuối cùng chúng sẽ hết thời gian và được đóng bởi máy chủ cơ sở dữ liệu.

+0

Bạn có thể mở rộng trên hồ bơi kết nối không? Và làm thế nào tôi sẽ thực hiện chúng? – Saobi

5

Trừ khi bạn đóng kết nối cụ thể, chúng sẽ vẫn mở cho đến khi hết thời gian chờ.

Tôi đã tìm ra điều này một cách khó khăn trong C# một vài lần. Các phương pháp hay nhất quyết định tắt/đóng tài nguyên mà bạn biết bạn sẽ không còn cần nữa. Lưu trữ các luồng I/O, kết nối DB, v.v.

+0

Điều đó có đúng ngay cả khi ứng dụng gặp sự cố không? (Không được phô trương, chỉ tò mò) –

+1

Tôi sẽ tưởng tượng như vậy. Ý tôi là, nếu bạn có một thử/nắm bắt và bạn đang ở giữa chỉnh sửa một tập tin và tôi giật dây nguồn. Các khoản tiết kiệm đó sẽ bị mất trong tình trạng lấp lửng .... –

+0

Tôi nghĩ điều này phụ thuộc vào loại sự cố. Một số sự cố có thể ảnh hưởng đến thời gian chạy (như giật dây nguồn, tràn ngăn xếp, v.v.) vì vậy trong trường hợp đó, kết nối sẽ vẫn mở cho đến khi hết thời gian chờ. Tuy nhiên, nếu một ngoại lệ đơn giản được ném ra, tôi nghĩ rằng thời gian chạy sẽ vẫn cố gắng đóng kết nối (nếu trong khối 'cuối cùng') –

6

Khi chấm dứt một quá trình, tất cả các tài nguyên liên quan (bao gồm bộ nhớ, xử lý, kết nối, ...) sẽ được giải phóng.

Thông thường, trong C#, bạn sẽ sử dụng câu lệnh Dispose pattern/using để kiểm soát các tài nguyên khan hiếm.

+1

Theo hiểu biết tốt nhất của tôi, tôi tin rằng bạn đúng. Những gì tôi thấy tò mò là PSU_Kardi tuyên bố ngược lại và có nhiều upvotes hơn. Vậy ai là người đúng? –

+0

@MasterPeter: Điều này chắc chắn là một điều nền tảng phụ thuộc. Nhưng trên hầu hết các hệ thống chính tôi đã thấy, đây là trường hợp. –

+0

Upvote không đúng thứ tự sửa chữa. –

-1

Nó phải được xóa trên GC tiếp theo, nhưng để được chính xác, trong C# bạn có thể đóng kết nối trên khối cuối cùng của xử lý ngoại lệ có cấu trúc.

try { 
    // open DB connection 
} catch (Exception ex) { 
    // deal with exception 
} finally { 
    // close and dispose connection 
} 
+0

Ok. nhưng nếu tôi có các câu lệnh kết nối db trải rộng trong suốt chương trình của tôi, để tôi không thể đặt chúng lại với nhau trong một lần thử/bắt/cuối cùng. Tôi có nên đưa chương trình TOÀN BỘ của tôi vào một khối thử/nắm bắt/cuối cùng lớn, vì vậy bất cứ khi nào có bất kỳ lỗi không mong muốn nào xảy ra thì db của tôi sẽ bị đóng? Nhưng đặt tất cả mọi thứ trong một thử lớn/bắt/cuối cùng là không duyên dáng? – Saobi

+0

Errr ... GC ở đâu khi quá trình không tồn tại? –

+1

Saobi: bạn nên chia mã DB thành nhiều phần dễ quản lý hơn và đặt khối try/catch trên mỗi khối. Curt: đây là TRƯỚC KHI quá trình thoát, tốt hơn là chỉ chấm dứt quá trình bởi vì bạn không thể đảm bảo chấm dứt bất thường sẽ luôn đóng kết nối. –

0

Hành vi chung của POSIX là khi chương trình chấm dứt, tất cả các xử lý tệp, kết nối mạng và vân vân sẽ bị đóng. Cho dù đầu kia làm điều đúng tại thời điểm đó là một câu hỏi mở, nhưng nếu bạn đang sử dụng bất kỳ RDBMS phổ biến hợp lý, nó sẽ được sử dụng tốt.

1

Trong C#, dọn dẹp ngầm được thực hiện bởi bộ thu gom rác nếu trình kết thúc được thực hiện trong đối tượng đang được thu thập rác. Bất kỳ việc dọn dẹp tài nguyên không được quản lý nào, chẳng hạn như các kết nối cơ sở dữ liệu, có thể được thực hiện trong phương thức Vứt bỏ.

Xem bài viết này để biết thêm thông tin:

thực hiện Hoàn thiện và Vứt bỏ sạch để lên Switch Tài
http://msdn.microsoft.com/en-us/library/b1yfkh5e(VS.71).aspx

1

Khi quá trình chấm dứt, tất cả các mô tả tệp đã mở sẽ được hệ điều hành phát hành. Các bộ mô tả tệp bao gồm các tệp và các ổ cắm, thường sẽ bao gồm các kết nối cơ sở dữ liệu của bạn.

Tất cả điều đó cho bạn biết rằng khi bạn khách hàng chấm dứt kết nối của nó sẽ bị đóng. Nó không cho bạn biết máy chủ làm gì. Tùy thuộc vào cách nó được viết, hoàn toàn có thể là máy chủ sẽ tiếp tục giữ các kết nối của nó mở, mong đợi các tin nhắn từ khách hàng sẽ không bao giờ đến, hoặc thậm chí cố gắng gửi dữ liệu. Đây có lẽ sẽ hết thời gian chờ, nhưng điều này có thể không được lên kế hoạch tốt. (Nên, đối với một RDBMS phong nha, nhưng nó có thể không.) Vì vậy, tùy thuộc vào RDBMS của bạn, bạn có thể cần thực hiện một số bước để báo cho máy chủ biết bạn đang đi xuống để nói nó giải phóng tài nguyên của nó.

1

Nếu bạn đang làm việc với SQL Server, bạn có thể xem trong sysprocesses hoặc chạy sp_who2. Tôi đã thử nghiệm này trên máy tính của tôi và các kết nối không nhận được đóng lại, ví dụ:

Console.Write("Opening connection"); 
Console.ReadLine(); 
SqlConnection connection = new SqlConnection(@"Data Source=.\SQLEXPRESS;Initial Catalog=SeniorMail;Integrated Security=SSPI;"); 
connection.Open(); 
SqlCommand command = new SqlCommand("SELECT count(*) from Account", connection); 
Console.Write("Running sql"); 
Console.ReadLine(); 
int? count = command.ExecuteScalar() as int?; 
Console.Write("Now I'll throw an exception"); 
Console.ReadLine(); 
int a = 0, b = 1, c = 0; 

try 
{ 
    c = b/a; 
} 
catch 
{ 
    Environment.Exit(1); 
} 

Tôi đã kiểm tra sp_who2 hai bên "Bây giờ tôi sẽ ném một ngoại lệ", và tôi có thể nhìn thấy kết nối đã biến mất sau khi ứng dụng thoát.

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