Avoiding hard-coded strings while raising or handling PropertyChanged event

While developing WPF/Silverlight applications, and more specifically while following the Model-View-ViewModel (MVVM) pattern we will find ourselves implementing INotifyProprertyChanged most of the times. The default implementation of PropertyChanged event takes the property name as string in the PropertyChangedEventArgs which is not much robust. There are several ways to address the issue:

  • Use reflection to verify that the property actually exists, as demonstrated once by Josh Smith.
  • Use Injection using some Aspect Oriented Programming framework, like PostSharp
  • Use Expression Trees as described by Michael Sync and Davy Brion

Personally, I prefer using expression trees. So, instead of writing this:

public string MyProperty
{
    get { return this.myProperty; }
    set { this.myProperty = value; this.RaisePropertyChanged("MyProperty"); }
}

We can write:

public string MyProperty
{
    get { return this.myProperty; }
    set { this.myProperty = value; this.RaisePropertyChanged( MyObj => MyObj.MyProperty ); }
}

The same issue exists looking at the other side. When we subscribe to PropertyChanged event of an object, we get the property name again as a string. One way is to use the GetPropertyName( ExpressionTree ) extension method from the above implementation in our if and case statements. Also, Josh nicely addressed the issue in this post, thus allowing us to write:

MyClass myObject = new MyClass();
PropertyObserver<MyClass> observer = new PropertyObserver<MyClass>(myObject)
    .RegisterHandler(myObj => myObj.MyProperty1, myObj => { /* handle change in MyProperty1 */ })
    .RegisterHandler(myObj => myObj.MyProperty2, MyProperty2HandlerMethod  );

Notice that Josh used IWeakEventListener that isn’t available for Silverlight but luckily Pete O’ Hanlon provided us with a Silverlight version of Josh’s work here.

So, combining the great efforts of all these people, we are going to have a better MVVM experience.

SSMS: How to restore differential backups

There are two ways to restore a differential backup in SQL Server:

  • Directly use TSQL statements as described in this MSDN page
  • Use SQL Server Management Studio user interface as described here.

If you are using SQL Management Studio to restore differential backups, and you have restored full backups several time using SSMS, but this is your first time to restore a differential backup then you are likely to encounter the following error:

Restore failed for Server 'servername'. (Microsoft.SqlServer.SmoExtended)
ADDITIONAL INFORMATION:
System.Data.SqlClient.SqlError: The log or differential backup cannot be restored because no files are ready to rollforward. (Microsoft.SqlServer.Smo)

This is because you tried to restore a differential backup on an available/operational/functional/running database which is not allowed.

In order to restore a differential backup, you will first need to restore the last full backup with NO RECOVERY option. So, in SSMS you need to select the appropriate full-backup and choose Restore With NoRecovery option from the Options page as depicted in the following screenshot.

restore-full-backup-with-norecovery

Once restored, the database will be shown in the Object Explorer as Restoring.

database-in-restore

Notice that the database is non-available/non-functional at this time and is waiting for a differential backup to be applied. Now, restore the appropriate differential backup and choose Restore With Recovery from the Options page:

restore-differential-backup-with-recovery

That’s it. You have successfully restored a differential backup.

A Final Note:

Note that differential backups are cumulative and each differential backup contain changes since the last full backup, not the last differential backup. So if you have a full backup of 2009-01-01 and have differential backups for each day, and you want to restore your database to 2009-01-10, then you just need to restore the full backup (with no recovery) of 2009-01-01 followed by the differential backup of 2009-01-10. For more information, read the following MSDN articles from SQL Server books online:

Entity Framework: Creating a model using views instead of tables

In Entity Framework, Views are “readonly” due to the DefiningQuery element. There are two approaches to make a view editable:

  1. Create stored procedures for Insert/Update/Delete: This is described in this document and this walkthrough.
  2. Make Entity Framework treat views as tables by doing some manual modifications in the generated EDMX file: This is described in this post.

A few days back, I created an entity model on top of views instead of tables. Since my physical model consisted of Views and not tables, so Entity Designer was not able to infer primary keys/relations etc., and I had to create them manually. In this post, I will highlight the steps I took to create a working entity model by hand. Please read at your own risk and feel free to contribute your ideas using the comments section. Note that not all views are updatable, and this MSDN document describes certain properties that a view definition must hold in order to be updatable.

Assume we have a JobWBS and a ResourceAssignment view with a One-to-Many relationship as depicted below:

db-model

If we try to create an “ADO.NET Entity Data Model” for the above views, Visual Studio will generate a model similar to this one.

generated-model

Notice that the designer marked all fields as primary keys. We need to manually edit the generated edmx file by opening it with “XML editor”.

open-with-xml-editor

You will also notice the following warnings inside the edmx xml:

Errors Found During Generation:
warning 6002: The table/view 'testdb.dbo.vw_JobWBS' does not have a primary key defined. The key has been inferred and the definition was created as a read-only table/view.

Read the rest of this entry »

RIA Services: How dates are handled and sent across the wire

The current(July) preview of RIA Services handles DateTime objects in an strange manner. Many of silverlight developers have complained in Silverlight forums that their dates are messed up. In this post, I am listing down several observations as a reference. Note that my current settings are +6 GMT.

From 	DateTime.Kind 	 DateTime.Value        To     DateTime.Kind  DateTime.Value
---- 	-------------   ----------------       --     -------------  ---------------
Client 	Unspecified     2009-01-01 00:00     Server 	Utc         2008-12-31 18:00
Server 	Unspecified     2009-01-01 00:00     Client 	Utc         2008-12-31 18:00
Client 	Local 	        2009-01-01 00:00     Server 	Utc         2008-12-31 18:00
Server 	Local 	        2009-01-01 00:00     Client 	Utc         2008-12-31 18:00
Client 	Utc 	        2009-01-01 00:00     Server 	Utc         2009-01-01 00:00
Server 	Utc 	        2009-01-01 00:00     Client 	Utc         2009-01-01 00:00

We can see that whatever Datetime we send, RIA service converts it to UTC when received at the other end. This could be bearable up to some extent but the worst thing is that RIA domain service treats Unspecified dates as Local and performs respective time zone conversion. Also, there is a UsesUtcDateTimes overridable in DomainService class but currently it does not seem to produce any effect.

Notice that there is no such conversion when using a WCF service, so whatever datetime value and kind we send from one side is exactlyreceived the same at the other side.

Lets hope the issues are fixed in the next version of RIA services.

My sample application that I used to test the behavior of RIA Domain Service and WCF Service can be downloaded from here. Remember to rename it to .zip for extraction.

Entity Framework: TimeStamp fields not recognized for optimistic concurrency model

Today, while working with Entity Framework, I noticed through SQL Profiler that my update queries were not using timestamp field. I looked into my model and found that my timestamp fields have Concurrency Mode property set to None. It was quite strange; The entity model was auto generated and I wonder why the EF designer could not identify my timestamp field (I remember Linq To SQL designer automatically took care of such fields). Anyway, I changed Concurrency Mode to Fixed and it worked great. So, as a final note, when generating entity model from database, don’t forget to set appropriate concurrency modes for your timestamp fields as it is not done by the designer itself.

setting concurrency mode for timestamp field

TSQL Challenge 11: Calculating the lowest price of an item by applying discount coupons

TSQL Challenge 11 was a practical problem. Given a a list of products and a list of discount coupons, we needed to find the minimum price for all the products based on certain rules. Here are those rules:

  • Maximum two coupons can be applied on the same product
  • The discount price can not be less than 70% of the original price
  • The total amount of the discount can not exceed 30$

Also, note that coupons are applied in a cumulative way. So the second coupon is applied on the result of the original price + first coupon.

Sample Data:
Here is some sample products data:

ID NAME    PRICE
-- ------- ---------
1  PROD 1  100,00
2  PROD 2  220,00
3  PROD 3  15,00
4  PROD 4  70,00
5  PROD 5  150,00

Here are the coupons to be applied

ID NAME         VALUE  IS_PERCENT
-- -----------  ------ ----------
1  CP 1 : -15$  15     0
2  CP 2 : -5$   5      0
3  CP 3 : -10%  10     1
4  CP 4 : -12$  12     0

And here’s the required output:

ID NAME    PRICE    DISC_PRICE  TOT_DISC  RATE    COUPON_NAMES
2.-- ------  -------- ----------- --------- ------- -------------------------
3.1  PROD 1  100.00$  73.00$      27.00$    27.00%  CP 4 : -12$ + CP 1 : -15$
4.2  PROD 2  220.00$  193.00$     27.00$    12.27%  CP 4 : -12$ + CP 1 : -15$
5.3  PROD 3  15.00$   13.50$      1.50$     10.00%  CP 3 : -10%
6.4  PROD 4  70.00$   49.50$      20.50$    29.28%  CP 1 : -15$ + CP 3 : -10%
7.5  PROD 5  150.00$  120.00$     30.00$    20.00%  CP 3 : -10% + CP 1 : -15$

Solution

Interesting enough… So lets attempt to find a solution. Read the rest of this entry »