Как пересечь метод сохранения на ActiveRecord на SubSonic ORM?

Мне нужно перехватить метод Save, выполнить некоторые проверки, изменить некоторые свойства и затем отпустить его снова в обычном режиме.

Как я могу это сделать?

Спасибо! Алекс


person AlexCode    schedule 18.08.2009    source источник
comment
ActiveRecord - довольно общий заголовок. Существует гораздо более широко используемая (и многие говорят лучше) библиотека O / RM, также использующая это слово; ActiveRecord, вероятно, из-за шаблона дизайна, который Мартин Фаулер придумал несколько лет назад и носил это имя. Таким образом, даже если вы отметили сообщение, чтобы люди могли понять, что вы говорите о Subsonic, правильнее было бы добавить Subsonic в заголовок ...   -  person Thomas Hansen    schedule 26.08.2009
comment
Вы правы ... совершенно забыли об универсальной среде stackoverflow. Больше не повторится :)   -  person AlexCode    schedule 26.08.2009


Ответы (4)


Я бы рекомендовал добавить следующие частичные методы, которые будут запускаться до их фактического действия:

OnSave(CancelEventArgs e); 
OnAdd(CancelEventArgs e); 
OnUpdate(CancelEventArgs e); 
OnDelete(CancelEventArgs e);

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

Эти два тоже должны быть добавлены к списку существующих, которые срабатывают после их фактического действия:

OnAdded(); 
OnUpdated();

Мне не нравится это имя OnAdded (), но если вместо Insert было принято Add, мы должны его придерживаться.

Вот и все ... С этими частичными элементами, я думаю, мы охватываем все до и после реальных методов сохранения данных, что дает нам большую гибкость, чтобы делать все, что мы хотим, с нашими данными.

Я могу реализовать это, но я всегда боюсь касаться файлов tt, потому что будущие обновления сотрут все мои пользовательские изменения! :)

Спасибо! Алекс

person AlexCode    schedule 23.08.2009

В 2.x были методы BeforeInsert и BeforeUpdate, которые можно было переопределить.

Думаю, в файл ActiveRecord.tt нужно добавить метод OnSaving. Поместите это рядом с подписью OnSaved ():

  partial void OnSaving();

Затем обновите файл ActiveRecord.tt. 2 изменения, которые я вижу:

Обновите метод обновления

    public void Update(IDataProvider provider)
    {      
    <#if(tbl.Columns.Any(x=>x.Name=="ModifiedBy")){#>
        if(String.IsNullOrEmpty(this.ModifiedBy))
            this.ModifiedBy=Environment.UserName;
     <#}#>
    <#if(tbl.Columns.Any(x=>x.Name=="ModifiedOn")){#>
        this.ModifiedOn=DateTime.Now;
     <#}#>

       **OnSaving();**

        if(this._dirtyColumns.Count>0)
            _repo.Update(this,provider);
        OnSaved();
   }

а затем обновите метод Add

public void Add(IDataProvider provider)
{ 
<#if(tbl.Columns.Any(x=>x.Name=="CreatedOn")){#>

            this.CreatedOn=DateTime.Now;
<#}#>
<#if(tbl.Columns.Any(x=>x.Name=="CreatedBy")){#>
            if(String.IsNullOrEmpty(this.CreatedBy))
                this.CreatedBy=Environment.UserName;
<#}#>
<#if(tbl.Columns.Any(x=>x.Name=="ModifiedOn")){#>
            this.ModifiedOn=DateTime.Now;
<#}#>
<#if(tbl.Columns.Any(x=>x.Name=="ModifiedBy")){#>
            if(String.IsNullOrEmpty(this.ModifiedBy))
                this.ModifiedBy=Environment.UserName;
<#}#>

            **OnSaving();**            

            var key=KeyValue();
            if(key==null){
                var newKey=_repo.Add(this,provider);
                this.SetKeyValue(newKey);
            }else{
                _repo.Add(this,provider);
            }
            SetIsNew(false);
            OnSaved();
}

Наконец, вам нужно использовать частичные классы, чтобы переопределить метод OnSaving () для обновления значений. Я делаю что-то очень похожее, так как я не использую соглашения Modifiedby и createdon (у меня там есть подчеркивания).

person Jim W    schedule 25.08.2009
comment
Да ... почти все. Я просто еще не сделал этого, потому что боюсь будущих дозвуковых обновлений ТТ. Как вы обрабатываете свои индивидуальные изменения? Другое дело, что мне нужно иметь возможность отменить изменения до фактического действия, поэтому мне нужны CancelEventArgs для методов On *. - person AlexCode; 26.08.2009
comment
У тебя действительно нет выбора. Если вам это нужно, вам придется отредактировать файлы tt. Я также хотел бы, чтобы OnSaving был добавлен к шаблонам по умолчанию (что-то подобное было в предыдущем выпуске, так что есть шанс, что он будет принят). Вы можете опубликовать проблему на сайте SubSonic на github (в рамках проекта subsonic-3 / templates). Он может быть рассмотрен и добавлен в более позднюю версию. Мне тоже не нравится редактировать файлы tt (я бы предпочел просто создавать частичные классы, когда это возможно), но если вам нужно, чтобы это работало, вам придется это сделать. - person Jim W; 26.08.2009
comment
Поскольку вам нужно отменить его, искали ли вы метод проверки? Раньше он существовал в 2.x, и я думаю, что он был вызван до запуска команд Insert / Update. Я думаю, у вас был способ отменить вставку / обновление, установив его недействительным. Я новичок в 3, поэтому у меня есть только предыдущий выпуск, чтобы сравнить его. - person Jim W; 26.08.2009

Вы можете использовать механизм частичного класса для создания собственной версии Save, которая выполняет проверку и вызывает сгенерированное SubSonic Save. например

namespace YourNameSpace
{
   public partial class YourTable : IActiveRecord
   { 
       public void MySave()
       {
           // insert your validation here
           this.Save()
       }
   }
}
person sparks    schedule 18.08.2009
comment
Привет дружище, спасибо за ответ. Это не совсем хороший вариант, потому что легко забыть о настраиваемом сохранении и использовать ActiveRecord по умолчанию. Мне не нужна перегрузка, мне нужно что-то вроде метода OnSave (отправитель объекта, CancelEventArgs e), где я могу проверить, изменить или даже отменить процесс сохранения независимо от используемой перегрузки сохранения. Я спрашивал, потому что я мог чего-то упустить, но если нет, мне придется реализовать это сам. - person AlexCode; 19.08.2009

Каждый класс ActiveRecord поставляется с частичным методом OnSave (), поэтому все, что вам нужно сделать, это создать частичный, а затем переопределить частичный OnSave () - точно так же, как в Linq To Sql:

public partial class MyClass{
   partial OnSave(){
   //magic
   }

}
person Community    schedule 21.08.2009
comment
Привет, Роб, спасибо за ответ. Дело в том, что доступен частичный метод OnSaved (), который указывает, что он вызывается после инструкций Save (). Когда это на самом деле запускается, до или после фактического Save ()? Спасибо! Алекс - person AlexCode; 23.08.2009
comment
Я видел это в коде ... он вызывается в конце методов Add & Update, и это не решает мою проблему. Мне нужно изменить данные объекта перед сохранением. Я добавлю возможное решение, потому что здесь комментарии могут содержать только 600 символов. - person AlexCode; 23.08.2009