Сигналы в Linq к Sql?

Как насчет ASP.NET MVC framework ? Это то, на чем работает этот сайт.

Еще один более зрелый вариант - Castle MonoRail .

Я думаю, что ASP.NET MVC, вероятно, лучший выбор в долгосрочной перспективе. Через год будет гораздо проще нанять того, кто знает ASP.NET MVC, чем того, кто знает MonoRail.

9
задан tghw 19 June 2009 в 02:59
поделиться

2 ответа

Хорошо, я полностью провалился в кроличью нору на этом, но я думаю, что у меня есть довольно крутое решение:

Во-первых, добавьте обработчик событий в контекст данных, который будет собрать все сигналы после сохранения и скрыть метод 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);
    }
}

Это немного сложно, поэтому, если что-то не имеет смысла, оставьте комментарий, и я сделаю все возможное, чтобы его исправить.

1
ответ дан 5 December 2019 в 02:08
поделиться

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.

1
ответ дан 5 December 2019 в 02:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: