Ok, mam już całkowicie w dół króliczej nory na ten jeden, ale myślę, że mam całkiem fajne rozwiązanie:
pierwsze, dodać obsługi zdarzeń do kontekstu danych, które będą zbierać wszystkie stanowiska -Zapisz sygnały i ukryj metodę Dispose
, abyśmy mogli wywołać zdarzenie tuż przed pozbyciem się. (Zauważ, że używam new
słowa kluczowego zamiast override
. To sprawia, że wywołanie zdarzenia możliwe.)
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);
}
}
Następnie napisać T4 Template że kontroluje plik dbml
że LINQ do SQL generuje dla Ciebie.
<#
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)
{
#>
...
Dla każdej tabeli w bazie danych (a tym samym dla każdej klasy częściowej) dodaj do części z następującymi metodami.
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
Dodaj również inny partial MyDataContext
przez T4. To doda definicje do częściowych metod, które Linq do SQL daje (jak wspomniał 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);
}
// ...
}
Ukryj te pliki w bezpiecznym miejscu, aby nikt nie próbował z nimi zadzierać.
Twoje ramy sygnałów są skonfigurowane. Teraz możesz pisać swoje sygnały. Umieścić je zarówno w Foo.cs
lub wszystkie razem w pliku Signals.cs
:
partial class Foo
{
partial void PostInsert()
{
EventLog.AddEvent(EventType.FooInserted, this);
}
}
To jest trochę skomplikowane, więc jeśli coś nie ma sensu, proszę zostawić komentarz i zrobię co w mojej mocy, aby go rozwiązać.