2009-08-06 12 views
5

Al usar LINQ-to-SQL, me gustaría crear automáticamente registros secundarios al insertar la entidad principal. Básicamente, imitar cómo funcionaría un desencadenador SQL Insert, pero en código para que se pueda realizar un procesamiento adicional.Imitando el desencadenador de inserción de SQL con LINQ-to-SQL

El elemento primario tiene una asociación con el elemento secundario, pero parece que no puedo simplemente agregar registros secundarios nuevos durante el DataContext SubmitChanges().

Por ejemplo,

public partial class Parent 
{ 
    partial void OnValidate(System.Data.Linq.ChangeAction action) 
    { 
     if(action == System.Data.Linq.ChangeAction.Insert) 
     { 
      Child c = new Child(); 
      ... set properties ... 
      this.Childs.Add(c); 
     } 
    } 
} 

Esto sería lo ideal, pero por desgracia, el recién creado Child registro no se inserta en la base de datos. Tiene sentido, dado que el DataContext tiene una lista de objetos/enunciados y probablemente no le gusta que se agreguen nuevos elementos en el medio.

De forma similar, al interceptar la función partial void InsertParent(Parent instance) en el DataContext e intentar agregar el registro Child, se obtiene el mismo resultado: sin errores, pero sin agregar nada a la base de datos.

¿Hay alguna manera de obtener este tipo de comportamiento sin agregar código a la capa de presentación?

Actualización: Tanto los OnValidate() y InsertParent() se abren desde la función de la DataContext SubmitChanges(). Sospecho que esta es la dificultad inherente a lo que estoy tratando de hacer: DataContext no permitirá la inserción de objetos adicionales (por ejemplo, a través del InsertOnSubmit()) mientras está en el proceso de enviar los cambios existentes a la base de datos.

Idealmente, me gustaría mantener todo bajo una transacción para que, si se produce algún error durante la inserción/actualización, nada realmente se cambia en la base de datos. De ahí mis intentos de imitar la funcionalidad del Trigger SQL, permitiendo que los registros secundarios se inserten automáticamente a través de una única llamada a la función SubmitChanges() de DataContext.

Respuesta

6

Si desea que suceda justo antes de que se guarde; puede anular SubmitChanges, y llamar al GetChangeSet() para obtener los cambios pendientes. Buscar las cosas que le interesan (por ejemplo, delta.Inserts.OfType<Customer>(), y realice los cambios necesarios.

Entonces llamada base.SubmitChanges(...).

Here's a related example, el manejo de eliminaciones.

+0

Marc - muchas gracias. ¡Eso es exactamente lo que estaba buscando y funciona perfectamente! – BrandonB

+0

Marc, este (y su enlace relacionado) es una sugerencia excelente y también fue muy útil para mí, ¡gracias! – Funka

2

El método Add solo establece un enlace entre los dos objetos: no marca el elemento agregado para su inserción en la base de datos. Para eso, necesita llamar al InsertOnSubmit en la instancia Table<Child> contenida en su DataContext. El problema, por supuesto, es que no existe una forma innata de acceder a su DataContext desde el método que describe.

Usted tiene acceso a él implementando InsertParent en su DataContext, entonces iría por esa ruta (y use InsertOnSubmit en lugar de , por supuesto).

EDITADO que supone que el método parcial InsertParent sería llamado por el DataContext en algún momento, pero en el estudio de mi propio código de ese método parece definirse pero nunca referenciado por la clase generada. Entonces, ¿de qué sirve, me pregunto?

+0

Mi opinión es exacta: los objetos "secundarios" deben agregarse al DataContext por medio de "InsertOnSubmit" para ser almacenados cuando se llama a SubmitChanges(). –

+0

Ben: se llamará a un método parcial, si es realmente implementado. Mientras solo esté definido (pero no implementado), no pasa nada. –

+0

Correcto, pero todavía tiene que haber un punto de llamada. En mi ejemplo DataContext, no puedo encontrar ninguna llamada a estos métodos parciales por el código generado. –

0

En linq a sql se crea un "desencadenante" haciendo una clase parcial al archivo dbml, y luego insertando un método parcial. Aquí hay un ejemplo que no haría nada porque llama a la eliminación incorporada.

Cuestiones relacionadas