Как насчет ASP.NET MVC framework ? Это то, на чем работает этот сайт.
Еще один более зрелый вариант - Castle MonoRail .
Я думаю, что ASP.NET MVC, вероятно, лучший выбор в долгосрочной перспективе. Через год будет гораздо проще нанять того, кто знает ASP.NET MVC, чем того, кто знает MonoRail.
Хорошо, я полностью провалился в кроличью нору на этом, но я думаю, что у меня есть довольно крутое решение:
Во-первых, добавьте обработчик событий в контекст данных, который будет собрать все сигналы после сохранения и скрыть метод 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 Template , который проверяет 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
Также добавьте еще один частичный 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);
}
}
Это немного сложно, поэтому, если что-то не имеет смысла, оставьте комментарий, и я сделаю все возможное, чтобы его исправить.
I have a much easier solution than what I already posted which didn't work anyway: override SubmitChanges(ConflictMode failureMode):
partial class MyDataContext
{
// SubmitChanges() calls this method after inserting default value for param
public override void SubmitChanges(ConflictMode failureMode)
{
// Pre-Submit Changes
//Updates
for (int changeCounter = 0; changeCounter < this.GetChangeSet().Updates.Count; changeCounter++)
{
var modifiedEntity = this.GetChangeSet().Updates[changeCounter];
// Do something, for example:
// var tableXEntry = new TableX() { Prop1 = "foo" };
// this.tableXEntries.InsertOnSubmit(tableXEntry );
}
//Inserts
for (int changeCounter = 0; changeCounter < this.GetChangeSet().Inserts.Count; changeCounter++)
{
object modifiedEntity = this.GetChangeSet().Inserts[changeCounter];
// Do Something
}
// Submit Changes
base.SubmitChanges(failureMode);
// Post Submit Changes
//Updates
for (int changeCounter = 0; changeCounter < this.GetChangeSet().Updates.Count; changeCounter++)
{
var modifiedEntity = this.GetChangeSet().Updates[changeCounter];
// Do something, for example:
// var tableXEntry = new TableX() { Prop1 = "foo" };
// this.tableXEntries.InsertOnSubmit(tableXEntry );
}
//Inserts
for (int changeCounter = 0; changeCounter < this.GetChangeSet().Inserts.Count; changeCounter++)
{
object modifiedEntity = this.GetChangeSet().Inserts[changeCounter];
// Do Something
}
}
With the Entity Framework, I do something similar to what you are trying to do: after I save a entity, I insert a new entry into a different table for auditing purposes (it's a copy of the entity before the changes). there is a SaveChanges() event on the EF entities container (like the data context) that allows you to add to the current context before changes are saved.