views:

46

answers:

2

Hi Guys,

If i have the following entity:

public class PocoWithDates
{
   public string PocoName { get; set; }
   public DateTime CreatedOn { get; set; }
   public DateTime LastModified { get; set; }
}

Which corresponds to a SQL Server 2008 table with the same name/attributes...

How can i automatically:

  1. Set the CreatedOn/LastModified field for the record to now (when doing INSERT)
  2. Set the LastModified field for the record to now (when doing UPDATE)

When i say automatically, i mean i want to be able to do this:

poco.Name = "Changing the name";
repository.Save(); 

Not this:

poco.Name = "Changing the name";
poco.LastModified = DateTime.Now;
repository.Save();

Behind the scenes, "something" should automatically update the datetime fields. What is that "something"?

I'm using Entity Framework 4.0 - is there a way that EF can do that automatically for me? (a special setting in the EDMX maybe?)

From the SQL Server side, i can use DefaultValue, but that will only work for INSERT's (not UPDATE's).

Similarly, i can set a default value using a constructor on the POCO's, but again this will only work when instantiating the object.

And of course i could use Triggers, but it's not ideal.

Because i'm using Entity Framework, i can hook into the SavingChanges event and update the date fields here, but the problem is i need to become "aware" of the POCO's (at the moment, my repository is implemented with generics). I would need to do some sort of OO trickery (like make my POCO's implement an interface, and call a method on that). I'm not adversed to that, but if i have to do that, i would rather manually set the fields.

I'm basically looking for a SQL Server 2008 or Entity Framework 4.0 solution. (or a smart .NET way)

Any ideas?

EDIT

Thanks to @marc_s for his answer, but i went with a solution which is better for my scenario.

+1  A: 

You have two options:

  • have a base class for all your business entity classes that does the

    poco.LastModified = DateTime.Now;
    

    in a virtual .Save() method that all others would have to call

  • use a trigger in the database

I don't think there's any other reasonably safe and easy method to achieve this.

marc_s
Can't do option 1. Save happens on the UnitOfWork (not the POCO's - i should have mentioned that, sorry). Hence me mentioning "SavingChanges" as a possibility. I dont really want to go down the trigger route (makes debugging a nightmare). Think i would rather manually set the fields in my service layer.
RPM1984
A: 

As i have a service layer mediating between my controllers (im using ASP.NET MVC), and my repository, i have decided to auto-set the fields here.

Also, my POCO's have no relationships/abstractions, they are completely independant. I would like to keep it this way, and not mark any virtual properties, or create base classes.

So i created an interface, IAutoGenerateDateFields:

public interface IAutoGenerateDateFields
{
   DateTime LastModified { get;set; }
   DateTime CreatedOn { get;set; }
}

For any POCO's i wish to auto-generate these fields, i implement this inteface.

Using the example in my question:

public class PocoWithDates : IAutoGenerateDateFields
{
   public string PocoName { get; set; }
   public DateTime CreatedOn { get; set; }
   public DateTime LastModified { get; set; }
}

In my service layer, i now check if the concrete object implements the interface:

public void Add(SomePoco poco)
{
   var autoDateFieldsPoco = poco as IAutoGenerateDateFields; // returns null if it's not.

   if (autoDateFieldsPoco != null) // if it implements interface
   {
      autoDateFieldsPoco.LastModified = DateTime.Now;
      autoDateFieldsPoco.CreatedOn = DateTime.Now;
   }

   // ..go on about other persistence work.
}

I will probably break that code in the Add out to a helper/extension method later on.

But i think this is a decent solution for my scenario, as i dont want to use virtuals on the Save (as i'm using Unit of Work, Repository, and Pure POCO's), and don't want to use triggers.

If you have any thoughts/suggestions, let me know.

RPM1984