Хорошо, я полностью провалился в кроличью нору, но думаю, у меня есть довольно крутое решение:
Сначала добавьте обработчик событий в ваш контекст данных, который будет собирать все сигналы после сохранения, и скрыть метод Dispose
, чтобы мы могли вызывать событие прямо перед тем, как утилизировать. (Обратите внимание, что я использую ключевое слово new
вместо override
. Это делает возможным вызов события.)
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);
}
}
Далее, напишите Шаблон T4 , который проверяет файл dbml
, который сгенерирует для вас Linq to Sql.
<#
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)
{
#>
...
Для каждой таблицы в базе данных (и, следовательно, для каждого частичного класса) добавьте частичное с помощью следующих методов.
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
Также добавьте еще один partial MyDataContext
через T4. Это добавит определения к частичным методам, которые предоставляет вам Linq to SQL (как упоминал Мерритт).
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);
}
// ...
}
Спрятать эти файлы в безопасное место, чтобы никто не пытался с ними связываться.
Ваша структура сигналов настроена. Теперь вы можете написать свои сигналы. Поместите их в Foo.cs
или все вместе в Signals.cs
файл:
partial class Foo
{
partial void PostInsert()
{
EventLog.AddEvent(EventType.FooInserted, this);
}
}
Это немного сложно, поэтому, если что-то не имеет смысла, пожалуйста, оставьте комментарий, и я сделаю все возможное, чтобы решить его.