Validaciones de transacciones en la base de datos

Problema: Tengo varios SPs que guardan información en la base de datos, pero deseo controlar que si alguno falla, la información de todos los SPs no se guarde.
Solución: Trabajar con la transaccionalidad que trae .Net.
Es obvio que las validaciones para las transacciones de escritura a la base de datos debe hacerse dentro del mismo SP, pero cuando se trabaja con varios SPs en el front-end, es decir, desde la capa del negocio, se debe realizar una validación adicional para controlar cualquier fallo que pudiera suceder desde la aplicación.
En realidad, validar las transacciones es fácil, solo se necesita añadir un SqlTransaction a la conexión que invoca al SP, pero en mi caso, que son varios SPs que realizan muchas escrituras a la base de datos, se debe tener un estricto control de la transaccionalidad.
Un ejemplo.
Tengo los siguientes SPs: sp_ingresar_cabecera, sp_ingresar_detalle, sp_registrar_historial, a los cuales debo mantener la secuencia estricta de grabación, es decir, si falla sp_registrar_historial, no debe grabarse sp_ingresar_cabecera ni sp_ingresar_detalle
Esto se logra realizando una opción general, que invoque a los 3 SPs y manteniendo la transacción dentro del mismo.
Private Sub Grabar()
 Using connection As SqlConnection = New SqlConnection(args)
  connection.Open() 'Abre la conexion
  Dim transaction As SqlTransaction 'Crea una variable de transaccion
  transaction = connection.BeginTransaction() 'Inicia la transaccion
  
  'Paso a la funcion la transaccion y la conexion
  if sp_ingresar_cabecera(transaction, connection) = False Then 
   transaction.Rollback() 'Si existe un error en la funcion que graba en el SP, se reversa la transaccion.
   Exit Sub
  End If
  if sp_ingresar_detalle(transaction, connection) = False Then 
   transaction.Rollback() 
   Exit Sub
  End If
  if sp_ingresar_detalle(transaction, connection) = False Then 
   transaction.Rollback() 
   Exit Sub
  End If
  
  transaction.Commit() 'Si todo esta correcto, la transaccion se graba en la base de datos.
  connection.Close()
 End Using
End Sub

Notese que las funciones que se llaman igual a los SPs de grabación se les envía como parámetro la transacción y la conexión, ésto sirve para que no se cree una conexion nueva en cada SP sino que se utilice la misma para todos los SPs, ayudando a que si existe una falla, todos los SPs se reversen.
Para probar que la transaccionalidad está funcionando se puede realizar el siguiente ejemplo.
En Microsoft Visual Studio, en modo de depuración, poner un punto de interrupción en alguno de los SPs que graban información, en el momento en que la información debería estar en la base de datos, como en la linea command.ExecuteNonQuery() o adapter.Fill(DataTable), o simplemente antes de la línea transaction.Commit()
Luego realizar una consulta a la base de datos en el motor de su preferencia, en mi caso es SQL Server y para ello utilizo el Microsoft SQL Server Management Studio y realizo un select sencillo a cualquiera de las tablas que estoy afectando directamente con el SP del Visual Studio.
Si la transaccionalidad está correcta, el select no mostrará ningún valor, y en el peor de los casos, la consulta se quedará congelada indefinidamente.
¿Cómo ésto puede ser bueno?, ¡Mi tabla se encuentra bloqueada! ¡No puedo acceder a ella!
Esta es una de las "bellezas" de la transaccionalidad, la tabla se "bloqueará" cuando se encuentre con una sentencia BeginTransaction y se "liberará" cuando se ejecute Rollback o Commit.
Es por eso que la transaccionalidad es una arma de doble filo, ayuda a que las acciones nunca se realicen si hay un problema, pero la tabla se bloquea hasta que la transacción termine.
Como recomendación, solo se debe usar la transaccionalidad en SPs o consultas que realicen modificación de datos, es decir, si hay Insert, Update o Delete, y no se debe utilizar para otras consultas.
La transaccionalidad ayuda a muchos problemas al momento de modificar los datos, porque, como en mi caso, se necesita que todos los datos sean coherentes para que existan en la base de datos, caso contrario, que ninguna información se grabe.

Vincular servidores SQL Server 2000

Problema: Necesito ejecutar un script (select) en otro servidor que no es el que estoy trabajando.
Solución: Servidores vinculados.

Esto de los servidores vinculados es todo un libro completo, es algo realmente complejo, largo y multifuncional, bien utilizado puede tener una enorme gama de posibilidades, pero para los que recién están empezando en el tema es abrumador.
No voy a ponerme a recitar todo lo que significa un servidor vinculado, puesto que para eso microsoft tiene su propio apartado. Servidores vinculados
Lo que queda de rescatar es la forma en que se vinculan dos servidores SQL Server 2000 entre sí, como lo que ocurrió en mi caso.
Mi problema era que necesitaba hacer algo así.
SELECT * FROM [servidor].[base_de_datos].[esquema].[tabla] WHERE [campo] = [@variable]

Por lo que, para realizar esto, se necesita tener un servidor vinculado.
Existe la opción gráfica, por medio del Management Studio, para crear la vinculación con solo de un par de clicks, pero cuando esa opción falla, por cualquier motivo, toca rompernos la cabeza intentando hacerlo por código.
Existe la opción de realizar el vinculo con otro servidor por medio del sp_addlinkedserver y de ello existe un montón de información en el internet.
Pero a mi no me funcionaba nada.
Sobre todo porque mi problema era poco común, y no se ajustaba a los ejemplos que ponían.
Explico un poco mejor.
En la ayuda de Microsoft, el primer ejemplo que se muestra es para vincular dos servidores SQL Server.
--En el siguiente ejemplo se crea un servidor vinculado llamado SEATTLESales. 
--El nombre del producto es SQL Server y no se utiliza ningún nombre de proveedor. 

USE master;
GO
EXEC sp_addlinkedserver 
   'SEATTLESales',
   N'SQL Server'
GO

Sencillo como el agua... Pero a mi no me funcionó.
Mi primer problema, el nombre de mi servidor. El nombre del servidor vinculado no permite caracteres extraños al ejecutar una consulta y para mi mala suerte, mi servidor es servidor-localidad-contador (con todo y guiones), por lo que al ejecutar un select, intenté hacerlo así.
SELECT * FROM servidor-localidad-contador.[base_de_datos].[esquema].[tabla]

Y me dio un lindo error que indicaba que la sentencia esta incorrecta por el - (guión).
Después estaba el problema del usuario y la contraseña, porque en el servidor origen tiene autenticación por Windows, mientras que el servidor destino es autenticación mixta. Por lo que el famoso usuario sa o dbo no funcionaba en el servidor vinculado.
También cabe recordar que ambos servidores eran SQL Server 2000.
Le di vueltas al asunto demasiado tiempo del que me permitía asumir, hasta que una ayuda, de las versiones anteriores al 2000 me dió la solución.
sp_addlinkedserver N'NombreDeLaVinculacion', ' ', N'SQLOLEDB', N'servidor-localidad-contador'

Nótese varias cosas.
NombreDeLaVinculacion es la palabra que uno debe escribir el en select antes del nombre de la base de datos, de preferencia debe ser una palabra corta sin signos especiales ni espacios.
' ' Tiene un espacio en blanco entre las comillas. Esto es importante, porque si no se pone el espacio en blanco no funcionará.
SQLOLEDB Esto, entre otras cosas, indica que se desea conectar a un servidor SQL Server de manera nativa. Creo que esto fue quitado para las versiones superiores, pero para la 2000 aún funciona.
servidor-localidad-contador Es el nombre de nuestro servidor, sea como sea que se llame, signos especiales incluidos, con instancias y todo. Si fuera con una instancia sería algo así: servidor-localidad-contador\instancia.
En realidad existen más parámetros que se pueden agregar, pero para mi caso, sólo éstos fueron necesarios.
Se que para versiones superiores al 2000 la vinculación es mucho más fácil, solo es cuestión de buscar un poco más en la documentación.
Luego, para ejecutar mi script (select), solo tuve que hacer lo siguiente.
SELECT * FROM NombreDeLaVinculacion.[base_de_datos].[esquema].[tabla]

Nota: Es obligatorio poner el esquema, puesto que muchas veces se la pasa por alto al poner dobles puntos, por ejemplo [base_de_datos]..[tabla], pero para esta opción del servidor vinculado, si no se pone el esquema, suele dar un lindo error de sentencia.
Espero que esto les ayude de alguna manera.