With Windows Phone 7.5 (aka Mango) we finally get access to SQL Server Compact via LINQ to SQL from within our applications. In my previous post Change Tracking with SQL Server Compact (LINQ to SQL) on Windows PhoneI demonstrated that you can make use of some additional functionality of SSCE that wouldn’t otherwise be accessible via the managed apis. One of the other things I encourage developers to do is to use Visual Studio or SQL Server Management Studio to actually create their database structure, then use the SqlMetal command line tool to generate the necessary class files. The main reason I do this is because there is an awful lot of repetitive code that you should implement for each table and column in your database. Not only is this a waste of your time to write, it’s also very likely you’ll insert an error or two and then waste countless hours trying to debug your code.
Ok, onto the topic of this post. Lets start with a minimal entity called Movie with appropriate attributes for use with LINQ to SQL:
[Table]
public class Movie {
[Column(IsPrimaryKey = true,
IsDbGenerated = true,
DbType = "INT NOT NULL Identity",
CanBeNull = false,
AutoSync = AutoSync.OnInsert)]
public int MovieId { get; set; }
[Column]
public string Name { get; set; }
[Column]
public int Year { get; set; }
}
Unlike most examples that you may have seen, the Movie class doesn’t implement either INotifyPropertyChanged or INotifyPropertyChanging. You might be thinking that these interfaces are required for LINQ to SQL to work properly. This is a complete fallacy, LINQ to SQL will work fine with this minimal implementation.
Here’s a couple of points about these two interfaces:
INotifyPropertyChanged
– You only need to implement this interface if you data class is going to change and you want those changes to propagate through to the UI.
– This interface is not required for LINQ to SQL to work
– This interface is not required to do read-once data binding
– If you’re going to be reading data from the data base and simply displaying it on the screen then you can, and should, leave this interface off as it just adds unnecessary clutter (KISS!)
INotifyPropertyChanging
– This interface is not required for LINQ to SQL to work
– This interface is not used by data binding
– You should however implement this interface to facilitate better memory management from LINQ to SQL
Here is an extract from the MSDN documentation around this interface.
http://msdn.microsoft.com/en-us/library/hh286406(v=VS.92).aspx#BKMK_MinimizingMemoryUsage
Let’s see this in action:
We’ll start with the Movie class without the INotifyPropertyChanging interface. The database is currently populated with a single Movie. We’ll run the following code and use the performance analysis tool in Visual Studio to examine what the impact is on memory.
var ms = dc.Movies.ToArray();
Thread.Sleep(5000);
Console.WriteLine("*******************************************");
Console.WriteLine(" We’re done!!!");
Console.WriteLine("*******************************************");
From the Debug menu load the Windows Phone Performance Analysis
Select Memory profiling and click the Launch Application link
Note that in the code above we were using Console.WriteLine to indicate when the 5 second sleep has finished. One of the issues with the performance tool is that because the debugger is not attached you can’t see anything in the Visual Studio Output window. However, the emulator does have a console window which you can enable so that you can see the Console.Writeline output.
Follow this link to enable the console window on your computer: Windows Phone 7 Console Window on 64 bit machine
Now, lets drill into the performance report. Note that you can see two instances of the Movie class have been loaded into memory. This is consistent with what the MSDN documentation said would happen.
Now, let’s implement INotifyPropertyChanging. For example the Name property now looks like this
private string name;
[Column]
public string Name
{
get { return name; }
set
{
if (name == value) return;
NotifyPropertyChanging("Name");
name = value;
}
}
And, let’s change our code so that in addition to loading the Movie into memory, we’ll change the Name property after five seconds.
var ms = dc.Movies.ToArray();
Thread.Sleep(5000);
ms.First().Name = "Changed name";
Thread.Sleep(5000);
Console.WriteLine("*******************************************");
Console.WriteLine(" We’re done!!!");
Console.WriteLine("*******************************************");
Now when we run the performance analysis we should see that for the first five seconds there is one Movie in memory. Then when we change the Name property a second instance is created to track the original and changed entities. This is hard to see in the performance tool as the Movie entity is tiny. However, thanks to John from Soul Solutions for pointing out this simple but effective trick I added a 10Mb byte array to the Movie class. This makes it much easier to see when each Movie instance is created in the performance analysis.
private byte[] bytes = new byte[1024*1024*10];
The output:
In the first time block there is a single Movie instance, as expected. Then when we modify the Name property (at approx 15 time marker) another 10Mb block is allocated to a second Movie instance. Of course, don’t forget to remove the 10Mb byte array when you are finished debugging your memory management!
This illustrates how important it is to implement INotifyPropertyChanging if you have a large number or large entities in your LINQ to SQL database.