Ok, me he vuelto completamente el agujero del conejo en este caso, pero creo que tengo una solución muy bien:
En primer lugar, añadir un controlador de eventos a su contexto de datos que recogerá todo del puesto -guarde las señales y oculte el método Dispose
para que podamos llamar al evento justo antes de desecharlo. (Nótese que uso la palabra clave en lugar de new
override
. Esto hace posible llamar al evento.)
partial class MyDataContext
{
internal delegate void PostSaveHandler();
internal event PostSaveHandler PostSave;
// This method hides the underlying Dispose because we need to call PostSave.
public new void Dispose(bool disposing)
{
// Obviously necessary error handling omitted for brevity's sake
PostSave();
base.Dispose(disposing);
}
}
A continuación, escribir una T4 Template que inspecciona el archivo dbml
que LINQ to SQL genera para usted.
<#
var dbml = XDocument.Load(@"MyDataContext.dbml");
var name = XName.Get("Type", "http://schemas.microsoft.com/linqtosql/dbml/2007");
var tables = from t in dbml.Descendants(name) select t.Attribute("Name").Value;
foreach(var table in tables)
{
#>
...
Para cada tabla en la base de datos (y por lo tanto cada clase parcial), agregue al parcial con los siguientes métodos.
public partial class Foo
{
internal void OnInsert(MyDataContext db) {
PreInsert();
db.PostSave += delegate { PostInsert(); };
}
internal void OnUpdate(MyDataContext db) {
PreUpdate();
db.PostSave += delegate { PostUpdate(); };
}
internal void OnDelete(MyDataContext db) {
PreDelete();
db.PostSave += delegate { PostDelete(); };
}
partial void PreInsert();
partial void PostInsert();
partial void PreUpdate();
partial void PostUpdate();
partial void PreDelete();
partial void PostDelete();
}
// repeat for all tables
También añada otro partial MyDataContext
vía T4. Esto agregará definiciones a los métodos parciales que Linq to SQL le brinda (como mencionó Merritt).
public partial class MyDataContext
{
// Add these three partial methods for each table
partial void InsertFoo(Foo foo)
{
foo.OnInsert(this);
ExecuteDynamicInsert(foo);
}
partial void UpdateFoo(Foo foo)
{
foo.OnUpdate(this);
ExecuteDynamicUpdate(foo);
}
partial void DeleteFoo(Foo foo)
{
foo.OnDelete(this);
ExecuteDynamicDelete(foo);
}
// ...
}
Oculte esos archivos en un lugar seguro, para que nadie intente meterse con ellos.
Su marco de señales está configurado. Ahora puedes escribir tus señales. Poner éstos ya sea en Foo.cs
o todos juntos en un archivo Signals.cs
:
partial class Foo
{
partial void PostInsert()
{
EventLog.AddEvent(EventType.FooInserted, this);
}
}
Esto es un poco complejo, por lo que si algo no tiene sentido, por favor deje un comentario y haré mi mejor esfuerzo para resolver el problema.