views:

40

answers:

2

Let's say I have a table in my database called Orders that has the following columns:

OrderId OrderDate CancelDate ShipDate LastActionDate

I want LastActionDate to always be the latest date of OrderDate, CancelDate, and ShipDate. What's the best way to accomplish this? Is there a way to handle the OnChanged event of those three dates so that the LastActionDate can be recalculated whenever those properties change? Or is there some built-in Linq 2 Sql magic that handles this scenario? Or do I just have to make sure to set the LastActionDate whenever I change any of the three dates?

A: 

If you want LastActionDate to be calculated, you shouldn't have it as a column in your database.

Assuming that the column is not in the database, it should not be part of the auto-generated L2S code either. This is good because it means that you can add it yourself, since the auto-generated L2S classes are partial classes.

Add a new C# code file and declare the Order class with the exact same signature as the auto-generated Order class, and add your calculated property. Something like this:

public partial class Order
{
    public DateTime LastActionDate
    {
        get
        {
            // pick the desired value from the other
            // three properties and return it
        }
    }
}

Note the partial keyword in the class declaration.

Mark Seemann
That's good in theory, but there are situations where these auto-calculated values come in handy (e.g. for calculating subtotals on orders for instance, or if the calculation is rather intense and not suitable for on-the-fly calculations). What do you do then?
Kevin Pang
I'm not sure I understand the problem, then. If a denormalized field is necessary, it would just be treated by L2S as any other field. OTOH, if you still want it to be calculated on the client, you can still use the partial class approach, but then cache the result of the calculation as a field in the class after having done the calculation once.
Mark Seemann
+1  A: 

In your Linq-to-SQL model, each property of each entity has a partial method called "(propertyname)Changed()".

Partial methods are a new feature of C# 3.0 - they're methods that are defined, but don't necessarily have an actual implementation. If they don't have an implementation, any call to them will be stripped out in the link phase of your build process.

However, if you do provide an implementation, then that implementation is indeed called. Since your entities classes such as Order are partial classes, you can easily create your own additional partial class and define those methods.

So in your case, you'll find OrderDateChanged(), CancelDateChanged() and ShipDateChanged().

From those methods, you can easily call up a method called CalculateLastActionDate() which would calculate your new date, as needed. Should be fairly easy.

public partial class Order
{
   void OrderDateChanged()
   {
       CalculateLastActionDate();
   }

   ......

   private void CalculateLastActionDate()
   {
      ... your implementation here
   }

}

Marc

marc_s