The Problem: All tables in our database have CreatedDate, CreatedBy, ChangedDate, ChangedBy fields which I want to be set automatically when Saving / Updating an ActiveRecord entity.
My first try was to override the Save() and Update() methods. But these methods only get called when I do a direct Save() or Update() on the entity. They are not being called in a Master - Detail scenario where I call Save() only on the master.
Next try were the OnSave() and OnUpdate() methods, but here changes in the fields were not persisted in the database.
Finally I tried the BeforeSave() method. But this method is not called when updating.
The Question: How can set these CreatedDate, CreatedBy, ChangedDate, ChangedBy fields automatically during a Save() or Update()?
To modify data as you you want you have to override the BeforeSave method like this:
protected override bool BeforeSave(IDictionary state)
{
bool retval = base.BeforeSave(state);
state["Password"] = Global.Encrypt("password");
return retval;
}
And finally save your instance:
protected void btnSave_Click(object sender, EventArgs e)
{
try
{
qfh.User user = null;
user = new qfh.User();
user.UserName = txtUserName.Text;
user.Name = txtName.Text;
user.IsAdministrator = cboIsAdministrador.SelectedValue == "Yes";
user.IsActive = cboIsActive.SelectedValue == "Yes";
user.SaveCopy();
}
catch (Exception ex)
{
ex = Utilities.GetInnerException(ex);
JSLiteral.Text = Utilities.GetFormattedExceptionMessage(ex);
}
}
I usually use SaveCopy() to make use of the overriden method FindDirty(object id, IDictionary previousState, IDictionary currentState, NHibernate.Type.IType[] types) to get the previous values of the class.
Hope it helps.
Use BeforeSave() for saving and OnFlushDirty() for updating.
you could do like this
[ActiveRecord("PostTable")]
public class Post : ActiveRecordBase<Post>
{
private int _id;
private DateTime _created;
[PrimaryKey]
public int Id
{
get { return _id; }
set { _id = value; }
}
[Property("created")]
public DateTime Created
{
get { return _created; }
set { _created = value; }
}
private void BeforeUpdate()
{
// code that run before update
Created = DateTime.Now;
}
public override void Update()
{
BeforeUpdate();
base.Update();
}
I had a same problem and solved it this way:
I use OnUpdate()
and OnSave()
. As you mentioned this solution does not work with master detail scenarios. For this I set parent of each child explicitly. Note following codes:
[ActiveRecord(Lazy = true)]
public class Lookup : ActiveRecordBase<Lookup>
{
[HasMany(typeof(LookupItem), Cascade = ManyRelationCascadeEnum.All)]
public virtual IList Items { set; get; }
//other properties...
}
[ActiveRecord(Lazy = true)]
public class LookupItem : ActiveRecordBase<LookupItem>
{
[BelongsTo("Lookup_id")]
public virtual Lookup ContainerLookup { set; get; }
//other properties...
}
void SaveLookup()
{
Lookup lookup = GetLookup();
LookupItem lookupItem = new LookupItem()
{
Title = LookupItemName,
ContainerLookup = lookup
};
lookup.Items.Add(lookupItem);
lookup.Save();
}
来源:https://stackoverflow.com/questions/1142156/howto-automatically-fill-fields-during-save-or-update-with-castle-activerecord