tgh*_*ghw 9 asp.net-mvc django-signals linq-to-sql
有没有人知道使用LINQ to SQL 做类似Django的signals方法?
我正在尝试记录何时插入新行以及更新某些列时,所以我真的只想要pre_save并post_save发出信号.
我可以通过使用定义为OnFooIDChanging()和OnFooIDChanged()(其中FooID是主键)的部分来对某些模型执行此操作,但这对于主键不是标识或由代码设置的模型不起作用.
对于那些,我可以使用OnValidate(),但这只会是pre_save,并且它使得处理数据库变得困难,因为OnValidate()调用来自DBContext.SubmitChanges(),当然不允许SubmitChanges()从内部调用第二个,使得post_save基本上不可能,就我而言可以看到.
好吧,我已经彻底陷入了这个问题,但我认为我有一个非常酷的解决方案:
首先,向数据上下文添加一个事件处理程序,该处理程序将收集所有保存后信号并隐藏该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)
这有点复杂,所以如果有什么不明白的地方,请发表评论,我会尽力解决它。
| 归档时间: |
|
| 查看次数: |
470 次 |
| 最近记录: |