Linq to Sql中的信号?

tgh*_*ghw 9 asp.net-mvc django-signals linq-to-sql

有没有人知道使用LINQ to SQL 做类似Django的signals方法?

我正在尝试记录何时插入新行以及更新某些列时,所以我真的只想要pre_savepost_save发出信号.

我可以通过使用定义为OnFooIDChanging()OnFooIDChanged()(其中FooID是主键)的部分来对某些模型执行此操作,但这对于主键不是标识或由代码设置的模型不起作用.

对于那些,我可以使用OnValidate(),但这只会是pre_save,并且它使得处理数据库变得困难,因为OnValidate()调用来自DBContext.SubmitChanges(),当然不允许SubmitChanges()从内部调用第二个,使得post_save基本上不可能,就我而言可以看到.

tgh*_*ghw 1

好吧,我已经彻底陷入了这个问题,但我认为我有一个非常酷的解决方案:

首先,向数据上下文添加一个事件处理程序,该处理程序将收集所有保存后信号并隐藏该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);
    }
}
Run Code Online (Sandbox Code Playgroud)

接下来,编写一个T4 模板来检查dbmlLinq 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)
{
#>
    ...
Run Code Online (Sandbox Code Playgroud)

对于数据库中的每个表(以及每个分部类),使用以下方法添加到分部。

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
Run Code Online (Sandbox Code Playgroud)

还可以通过 T4 添加另一个partial MyDataContext。这将为 Linq to SQL 为您提供的部分方法添加定义(如 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);
    }

    // ...
}
Run Code Online (Sandbox Code Playgroud)

将这些文件隐藏在安全的地方,这样就没有人试图弄乱它们。

您的信号框架已设置。现在您可以编写信号了。将它们放入Foo.cs或全部放入一个Signals.cs文件中:

partial class Foo
{
    partial void PostInsert()
    {
        EventLog.AddEvent(EventType.FooInserted, this);
    }
}
Run Code Online (Sandbox Code Playgroud)

这有点复杂,所以如果有什么不明白的地方,请发表评论,我会尽力解决它。