Ας περιγράψουμε τί έγινε. Έχεις ανοικτό connection και στο connection έχεις ανοικτό transaction. Σταματάς το debug το οποίο σημαίνει ότι σταματας απότομα την εκτέλεση κάθε κώδικα στο service. Μαζί και τον κώδικα που θα έκλεινε το connection στο server και θα οδηγούσε εμμέσως στο κλείσιμο του transaction. Βλέπεις, η σύνδεση στον SQL Server δεν είναι κάποιο handle σε κάποιο τοπικό αρχείο αλλά σύνδεση με sockets ή pipes σε κάποιο άλλο μηχάνημα, οπότε το λειτουργικό δεν ξέρει τί να κάνει για να την κλείσει. Έτσι, μένει ένα connection ορφανό το οποίο τυγχάνει και να περιέχει ένα ανοικτό transaction. Κακό παιδί!

Ευτυχώς, το ίδιο το λειτουργικό ελέγχει περιοδικά τις ανοικτές συνδέσεις TCPIP και Named Pipes στέλνοντας ένα keep-alive μήνυμα. Αυτό γίνεται κάθε 2 ώρες για το TCP/IP και κάθε ώρα για τα Named Pipes. Αυτή η ρύθμιση μπορεί να αλλάξει από το registry (KeepAliveTime και SessionKeepAlive αντίστοιχα) και ισχύει για όλες τις εφαρμογές που τρέχουν στο μηχάνημα, όχι μόνο τον SQL Server.
Αυτά για το DEBUG, το οποίο δεν καλεί destructors. Στην κανονική λειτουργία ένα unhandled exception θα έχει σαν αποτέλεσμα να τερματιστεί το service και να απελευθερωθούν όλα τα resources και να κληθούν και οι destructors κάθε αντικειμένου. Έτσι και το connection θα κλείσει κανονικά οδηγώντας σε rollback του ανοικτού transaction. Συνεπώς, δεν υπάρχει κίνδυνος να μείνει ανοικτό το transaction για μεγάλο διάστημα.
Δυστυχώς, δεν συμβαίνει το ίδιο αν συμβεί κάποιο άλλο απρόσμενο σφάλμα, π.χ. να βγει το καλώδιο δικτύου κατά λάθος ή να πέσει το switch ή να κολλήσει η κάρτα δικτύου ή ... να κλείσει ο debugger. Στην περίπτωση αυτή τα connections θα κλείσουν πάλι μόνο όταν το λειτουργικό ελέγχει για orphaned sessions.
Για περισσότερες πληροφορίες ψάξε στο MSDN ή Books Online για Orphaned Sessions.
Παναγιώτης Καναβός, Freelancer
Twitter: http://www.twitter.com/pkanavos