I have a lot of Entities in my model that inherit from an abstract class called BaseEntity.
Then there is an "Edit" controller that receives a Person object as a parameter and saves the changes. In the view for this "Edit" control the user can obviously edit some fields of the entity. The view only contains the PersonId
as a hidden field and the Name
as a textbox.
My Entities look something like this:
public abstract class BaseEntity
{
public DateTime DateCreated { get; set; }
public DateTime DateLastModified { get; set; }
public int? UserIdLastModified { get; set; }
}
public class Person : BaseEntity
{
int PersonId { get; set; }
string Name { get; set; }
}
And this is the controller:
[HttpPost]
public ActionResult Edit(Person person, FormCollection collection)
{
/* ... do something with the FormCollection */
db.Entry(person).State = EntityState.Modified;
db.SaveChanges();
}
I also override the db.SaveChanges() method so it will set the DateLastModified
field automatically. But because the DateCreated
will be DateTime.MinValue
, SaveChanges() throws an exception.
For privacy and simplicity, I don't want to add the fields of the BaseEntity as hidden fields to the View. I know I could load the entity from the database in the Controller and only update the Name
, but it doesn't strike me as the best solution because I would have to do that in a lot of "Edit" controllers. And everytime something changes in the Model I have to change the Controller and View.
What's a good way of getting DateCreated
back to the Controller before saving it?
EDIT:
Thanks for the answers already. However, this is my SaveChanges method. To answer some of the comments and explain a little further: the problem is that if I only set DateLastModified
like described below, base.SaveChanges() will try to overwrite DateCreated
with '1/1/0001 12:00:00 AM' (because it was never set). And this correctly throws the exception.
What I was trying to do now, is to add some logic to get the previous values of the BaseEntity in the SaveChanges method. Apparently I need to do another Database call somewhere and this way I have the logic only in one place instead of every Controller. If there is something wrong with that approach, please tell me.
public override int SaveChanges()
{
ObjectContext context = ((IObjectContextAdapter)this).ObjectContext;
//Find all Entities that are Added/Modified that inherit from my EntityBase
var objectStateEntries =
(from e in context.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified)
where e.IsRelationship == false && e.Entity != null && typeof(BaseEntity).IsAssignableFrom(e.Entity.GetType())
select e).ToList();
foreach (var entry in objectStateEntries)
{
var entityBase = (BaseEntity)entry.Entity;
if (entry.State == EntityState.Added)
{
entityBase.DateCreated = DateTime.UtcNow;
}
entityBase.DateModified = DateTime.UtcNow;
//new code for getting the previous value
if (entityBase.DateCreated == DateTime.MinValue)
{
//this is not working. just to show you my idea
var currentDBItem = this.Entry(entry.Entity).Entity as BaseEntity; //get previous value from database
entityBase.DateCreated = currentDBItem.DateCreated;
}
}
return base.SaveChanges();
}