Getting and setting the Transaction Isolation Level on a SQL Entity Connection

This article explains how to get, set, and reset the transaction isolation level on a SQL and Entity connection. In a previous article I already explained how important it is to explicitly set the appropriate isolation level when using transactions. I'm sure you're not going to wrap each and every database call in an explicit transaction (TransactionScope is simply too heavy to wrap around a simple SELECT statement). Nevertheless you should realize that every single T-SQL statement that you launch from your application will run in a transaction, hence will behave according to a transaction isolation level. 

If you don't explicitely start a transaction or use a transaction scope, then SQL Server will run the statement as a transaction on its own. You don't want your SQL commands to read unofficial data (in the READ UNCOMMITTED level) or apply too heavy locks (in the SERIALIZABLE level) on the database, so you want to make sure that you're running with the correct isolation level. This article explains how to do this.

Setting the Transaction Isolation Level

Setting the appropriate isolation level on a session/connection is done with a standard T-SQL statement, like the following:

T-SQL

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ


It's easy to write an extension method on the SqlConnection and EntityConnection classes that allows you to do this call in C#, like this:

C#

using (AdventureWorks2008Entities model = new AdventureWorks2008Entities())

{

    model.Connection.Open();

 

    // Explicitely set isolation level

    model.Connection.SetIsolationLevel(IsolationLevel.ReadUncommitted);

 

    // Your stuff here ...

}


Here's the whole extension method. I implemented it against IDbConnection to cover all connection types. The attached Visual Studio solution contains the full code:

C#

public static void SetIsolationLevel(this IDbConnection connection, IsolationLevel isolationLevel)

{

    if (isolationLevel == IsolationLevel.Unspecified || isolationLevel == IsolationLevel.Chaos)

    {

        throw new Exception(string.Format("Isolation Level '{0}' can not be set.", isolationLevel.ToString()));

    }

 

    if (connection is EntityConnection)

    {

        SqlConnection sqlConnection = (connection as EntityConnection).StoreConnection as SqlConnection;

        sqlConnection.SetIsolationLevel(isolationLevel);

    }

    else if (connection is SqlConnection)

    {

        IDbCommand command = connection.CreateCommand();

        command.CommandText = string.Format("SET TRANSACTION ISOLATION LEVEL {0}", isolationLevels[isolationLevel]);

        command.ExecuteNonQuery();

    }

}

 

Getting the Transaction Isolation Level

If you want to retrieve the current isolation level on your connection, you have to first figure out how to do this in T-SQL. Unfortunately there is no standard @@ISOLATIONLEVEL function or so. Here's how to do it:

T-SQL

SELECT CASE transaction_isolation_level

          WHEN 0 THEN 'Unspecified'

          WHEN 1 THEN 'Read Uncommitted'

          WHEN 2 THEN 'Read Committed'

          WHEN 3 THEN 'Repeatable Read'

          WHEN 4 THEN 'Serializable'

          WHEN 5 THEN 'Snapshot'

       END AS [Transaction Isolation Level]

  FROM sys.dm_exec_sessions

 WHERE session_id = @@SPID


Altough you're querying a dynamic management view, the code requires no extra SQL Permissions (not even VIEW SERVER STATE). A user can always query his own sessions.

Again, you can easily wrap this into an extension method, that can be called like this:

C#

using (AdventureWorks2008Entities model = new AdventureWorks2008Entities())

{

    model.Connection.Open();

 

    // Get isolation level

    // Probably returns 'ReadUncommitted' (due to connection pooling)

    MessageBox.Show(model.Connection.GetIsolationLevel().ToString());

}


If you run the same code from the attached project, you'll indeed notice that the returned isolation level will be -most probably- READ UNCOMMITTED. This is because we -most probably- reuse the connection from the SetIsolationLevel() sample. As I already mentioned in a previous article, the transaction isolation level is NOT reset on pooled connections. So even if you're not explicitly use transactions, you still should still set the appropriate transaction isolation level. There's no default you can rely on.

OK, here's the corresponding extension method:

C#

public static IsolationLevel GetIsolationLevel(this IDbConnection connection)

{

    string query =

        @"SELECT CASE transaction_isolation_level

                    WHEN 0 THEN 'Unspecified'

                    WHEN 1 THEN 'ReadUncommitted'

                    WHEN 2 THEN 'ReadCommitted'

                    WHEN 3 THEN 'RepeatableRead'

                    WHEN 4 THEN 'Serializable'

                    WHEN 5 THEN 'Snapshot'

                    END AS [Transaction Isolation Level]

            FROM sys.dm_exec_sessions

            WHERE session_id = @@SPID";

 

    if (connection is EntityConnection)

    {

        return (connection as EntityConnection).StoreConnection.GetIsolationLevel();

    }

    else if (connection is SqlConnection)

    {

        IDbCommand command = connection.CreateCommand();

        command.CommandText = query;

        string result = command.ExecuteScalar().ToString();

 

        return (IsolationLevel)Enum.Parse(typeof(IsolationLevel), result);

    }

 

    return IsolationLevel.Unspecified;

}


Simple and powerful, isn't it? Stuff like this should ship with the framework!

Temporarily using a Transaction Isolation Level

With the new GetIsolationLevel() and SetIsolationLevel() methods it becomes easy to set the isolation level to execute some commands, and then reset the level to its original value. I wrapped these calls in a class implementing IDisposable so you can apply the using statement, like this:

C#

using (AdventureWorks2008Entities model = new AdventureWorks2008Entities())

{

    model.Connection.Open();

 

    // Set and reset isolation level

    using (TransactionIsolationLevel inner = new TransactionIsolationLevel(model.Connection, IsolationLevel.Snapshot))

    {

        // Your stuff here ...

    }

}


Again, the code is very straightforward. All you need is a constructor, a Dispose-method, and a variable to store the original isolation level:

C#

/// <summary>

/// Transaction Isolation Level.

/// </summary>

public class TransactionIsolationLevel : IDisposable

{

    /// <summary>

    /// The database connection.

    /// </summary>

    private IDbConnection connection;

 

    /// <summary>

    /// Original isolation level of the connection.

    /// </summary>

    private IsolationLevel originalIsolationLevel;

 

    /// <summary>

    /// Initializes a new instance of the TransactionIsolationLevel class.

    /// </summary>

    /// <param name="connection">Database connection.</param>

    /// <param name="isolationLevel">Required isolation level.</param>

    public TransactionIsolationLevel(IDbConnection connection, IsolationLevel isolationLevel)

    {

        this.connection = connection;

        this.originalIsolationLevel = this.connection.GetIsolationLevel();

        this.connection.SetIsolationLevel(isolationLevel);

    }

 

    /// <summary>

    /// Resets the isolation level back to the original value.

    /// </summary>

    public void Dispose()

    {

        this.connection.SetIsolationLevel(this.originalIsolationLevel);

    }

}

 

Source Code

The attached project contains the extension methods, the IDisposable class, and some demo calls against a local AdventureWorks database:

Here it is: U2UConsult.SQL.TransactionIsolationLevel.Sample.zip (87,53 kb)

Enjoy!


Get your WCF client configuration from anywhere

An application that consumes one or more WCF services needs to provide the address, binding protocol, and contract (ABC) of each end point in its app.config file. This article shows an easy way to let the application get its WCF client configuration data from anywhere: a flat file, a database, even pigeon post if you like. The approach leverages the native XML configuration schema as well as the proxy generated by Visual Studio.NET. The following is a screenshot from the attached solutin, showing a WPF client that calls the canonical Hello World service synchronously and asynchronously, but using an end point configuration from a local string variable:

Rolling your own WCF custom client

Basically there are two approaches if you want to build a custom WCF client:

  • create your own proxy entirely from scratch , or
  • extend an existing proxy with a custom channel factory.

Both of these require extensive coding. In this article, I elaborate on the latter approach: I'll build a custom channel factory -derived from ChannelFactory<T>- that reads its WCF client configuration from a custom configuration file. Then I plug this channel factory into the proxy that was generated by Visual Studio.NET.

Oh wait, in the title of this article I mentioned that the configuration data could come from anywhere - not just a file. As it stands, we always need to persist the configuration data in a physical file. Some of the non-virtual members and constructors of the classes in the ChannelFactory<T> hierarchy use the System.Configuration namespace to parse the address, binding, and contract information. The classes in this namespace are specialized in reading configuration sections from physical XML configuration files à la app.config. These classes require a file path to do their work. So there's no way around a config file - at least a temporary one.

Creating a custom channel factory

When you create a custom channel factory, you inherit from ChannelFactory<T> and then override one of the following methods:

  • CreateDescription, or
  • ApplyConfiguration.

The attached solution at the end of this article uses the latter approach: it overrides ApplyConfiguration.

The code is borrowed from this msdn forum article. It reads the configuration from an arbitrary config file using the very same System.Configuration classes. This is convenient: we can copy/paste the -complex- config file from the project holding the service reference!

Reusing the svcutil proxy

It's perfectly possible to use a custom channel factory and still leverage all the code from the proxy that was generated by Visual Studio.NET through svcutil, e.g. the asynchronous calls and the fault classes. All you need to do is create a child class from the proxy, and override its CreateChannel method.

Here's the architecture:

Here's the CreateChannel method:

/// <summary>

/// Creates a channel that implements the service interface.

/// </summary>

/// <returns>A channel from the end point in the custom configuration file.</returns>

protected override IDummyService CreateChannel()

{

    CustomChannelFactory<IDummyService> factory =

        new CustomChannelFactory<IDummyService>(

            "IDummyServiceBinding", /* or use "*" for the first end point */

            this.configurationFilePath);

    return factory.CreateChannel();

}


At runtime, the first thing to do is fetching the configuration information from the store of your choice. The attached solution just uses a string variable:

private string endpointConfiguration =

    @"

        <configuration>

            <system.serviceModel>

                <bindings>

                    <basicHttpBinding>

                        <binding name='BasicHttpBinding_IDummyService' closeTimeout='00:01:00'

                            openTimeout='00:01:00' receiveTimeout='00:10:00' sendTimeout='00:01:00'

                            allowCookies='false' bypassProxyOnLocal='false' hostNameComparisonMode='StrongWildcard'

                            maxBufferSize='65536' maxBufferPoolSize='524288' maxReceivedMessageSize='65536'

                            messageEncoding='Text' textEncoding='utf-8' transferMode='Buffered'

                            useDefaultWebProxy='true'> etc.etc. etc.

 

Then we need to save this information in a file, preferably in a fast and safe place. The ideal candidate is of course Isolated storage.

Storing configuration files in isolated storage file

The following method saves the configuration information in isolated storage and returns the physical path to that file through a small hack (Reflection):

/// <summary>

/// Saves the configuration information in a file in isolated storage, and returns the path.

/// </summary>

/// <param name="configuration">XML configuration elements.</param>

/// <param name="fileName">Configuration file name</param>

/// <returns>Full path name of the configuration file.</returns>

private string GetConfigurationFilePath(string configuration, string fileName)

{

    // Create a file in isolated storage.

    IsolatedStorageFile store = IsolatedStorageFile.GetStore(IsolatedStorageScope.User | IsolatedStorageScope.Assembly, null, null);

    IsolatedStorageFileStream stream = new IsolatedStorageFileStream(fileName, FileMode.Create, store);

    StreamWriter writer = new StreamWriter(stream);

    writer.WriteLine(configuration);

    writer.Close();

    stream.Close();

 

    // Retrieve the actual path of the file (using Reflection).

    string proxyConfigurationPath = stream.GetType().GetField("m_FullPath", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(stream).ToString();

 

    return proxyConfigurationPath;

}

 

That went easy, so where's the catch ?

This solution comes with a small price: the app.config still needs an end point definition. This is because the constructor of ClientBase<T> -the base class of the Visual Studio proxy- parses the config file for a syntactically valid end point: there must be an address (a fake URI will do), a binding protocol (any type will do), and a full contract definition. This end point is never used however, because our child class overrides the creation of the channel. So we can get away with a dummy end point in the standard configuration file - only the contract needs to match:

<configuration>

  <system.serviceModel>

    <client>

      <!-- Look mom: no real configuration. -->

      <endpoint

        address="http://dummyAddress"

        binding="netMsmqBinding"

        contract="ServiceReference.IDummyService" />

    </client>

  </system.serviceModel>

</configuration>

 

Source code

Here's the sample solution: U2UConsult.WCF.Configuration.Sample.zip (98,53 kb)

Enjoy!


Transactions and Connections in Entity Framework 4.0

This article describes where, why, and how to use TransactionScope in the Entity Framework 4.0. The proposed best practices apply to a medium to large data access layer, e.g. a DAL that is implemented as one or more WCF services with lots of internal calls. Allow me to start with the conclusions:

  • Always execute all data base access inside a TransactionScope,
  • always explicitely specify an isolation level, and
  • always explicitely open the entities' connection.

If you trust me, implement these rules in all your projects. If you don't trust me, continue reading to figure out why.

Why you should open the connection explicitely.

So you decided to continue reading. Thanks for the confidence Smile.

Default data adapter behavior

Under the hood of the newest 4.0 Entity Framework, the real work is still done by ye olde ADO.NET 1.* data adapter. Such a data adapter needs a connection and a command to do its work. If the connection is open, the adapter executes the command and leaves the connection open. If the connection is closed, the adapter opens it, executes the command, and then politely closes the connection again. When using the Entity Framework, you can open the connection explicitely as follows:

using (AdventureWorks2008Entities entities = new AdventureWorks2008Entities())

{

    entities.Connection.Open();

 

    // Your stuff here ...

}


If you don't open the connection explicitely, it will be opened and closed for you. That is convenient, but in a busy complex data access layer the same physical connection will be openened and closed over and over again. I now hear you saying 'What's wrong with that, the connection is pooled anyway, so there's no overhead in opening and closing.' Well, actually the data adapters behavior comes with a price, and I'm sure you will not always want to pay that price.

Performance impact

Data base connections are not created each time you need one. In most cases a connection is fetched from the connection pool. A pooled connection is always first cleaned up by the .NET data client with a call to the sp_reset_connection system procedure. A complete list of that procedure's actions can be found here. The list includes the following:

  • It resets all error states and numbers (like @@error),
  • it stops all execution contexts (EC) that are child threads of a parent EC executing a parallel query,
  • it waits for any outstanding I/O operations,
  • it frees any held buffers on the server by the connection,
  • it unlocks any buffer resources that are used by the connection,
  • it releases all memory allocated to the connection,
  • it clears any work or temporary tables that are created by the connection,
  • it kills all global cursors owned by the connection,
  • it closes any open SQL-XML handles that are opened by the connection,
  • it deletes any open SQL-XML related work tables,
  • it closes all system tables,
  • it closes all user tables,
  • it drops all temporary objects,
  • it aborts open transactions,
  • it defects from a distributed transaction when enlisted,
  • it decrements the reference count for users in current database,
  • it frees acquired locks,
  • it resets all SET options to the default values,
  • it resets the @@rowcount value,
  • it resets the @@identity value,
  • it resets any session level trace options using dbcc traceon(), and
  • fires Audit Login and Audit Logout events.

If you don't explicitely open the connection yourself, then every other call will be a call to sp_reset_connection.

Please don't start panicking now: SQL Server does all of this extremely fast. The demo application that you find at the end of this article clearly shows that even a high number of calls to the procedure incurs no noticable performance impact. These numerous calls only disturb your monitoring experience with SQL Profiler. The following images show a profiler session where the same workload is executed with and without explicitely opening the connection:

Default behaviorExplicit open

 

Although every other SQL command is a call to sp_reset_connection, there's hardly any impact on the response time:

But anyway there ís a performance penalty, and you can avoid it.

Distributed transaction escalation

The continuing opening and closing of a (pooled) connection has more than just a small performanct impact when you're running inside a TransactionScope. It can cause a local transaction to escalate to a distributed transaction unnecesarily. When a transaction spans more than one resource manager (database or queuing system) or involves too many connections, the .NET client decides to call help from the Distributed Transaction Coordinator service (MSDTC) in the Operating System. When that escalation exactly takes place depends largely on the version of SQL Server you're working against. The more recent versions sustain local mode longer. I only have SQL Server 2008R2 instances in my network. These instances even allow multiple connections to share the same transaction without escalating to MSDTC. The only way to force an escalation on my machine, is disabling connection pooling in the connection string (by adding Pooling=False).

Escalating to a distributed transaction takes a lot of resources: different services need to initialize and communicate. Here's a screenshot of the demo application, compare the response time for a regular escalated call to the rest (the very first escalation -when stuff needs to be initialized- takes between 4 and 8 seconds):

Of course some of the observed overhead comes from the lack of pooling. Anyway, I believe that the difference in response time is high enough to catch your attention. You can strongly reduce the escalation risk by minimizing the number of physical connections per transaction by explicitely opening the connection and keeping it open until you commit. Here's again a comparison of profiler traces, with and without explicit opening:

Default behaviorExplicit open

Opening the connection brings the response time of the sample workload back to normal:

Why you should use TransactionScope

Local transactions can only escalate to distributed transactions when you're running in a TransactionScope. So you might decide not to use TransactionScope after all. Unfortunately this is not an option. One of the few things that sp_reset_connection doesn't do is resetting the transaction isolation level. I personally consider this a frakking bug. According to Microsoft, the behavior is by design so this bug will never be solved.

If you want tight control over the performance and scalability of your data access, then managing the isolation level is absolutely crucial. There are two ways to control the isolation level in a DAL method:

Explicitely starting a transaction

I see three ways to start a transaction:

  • using SQL statements BEGIN-COMMIT-ROLLBACK
  • starting a transaction on the connection using .NET code, or
  • using TransactionScope.

The good thing about the first two techniques is that their default isolation level is READ COMMITTED, which is a nice trade-off between performance (minimal locking overhead) and reliability (no dirty reads possible). For this reason, READ COMMITTED is the default isolation level in the ANSI and ISO standards. Of course you could specify another level, if required. I will not elaborate on T-SQL transactions. You should only use these inside stored procedures and batch scripts, never in C# programs. Here's an example on using C# to start a transaction on the connection. Inside the transaction, you always know the isolation level (because you set it, or because there is a reliable default):

using (AdventureWorks2008Entities entities = new AdventureWorks2008Entities(entitiesConnectionstring))

{

    entities.Connection.Open();

 

    // Always returns 'Read Committed'

    DbTransaction trx = entities.Connection.BeginTransaction();

    this.ErrorLabel.Content = trx.IsolationLevel.ToString();

 

    // Your stuff here ...

 

    trx.Commit();

}


In the context of a larger application, these first two techniques are too tightly connected to the database: you need a reference to the physical connection to control the transaction and its isolation level. So these techniques are only applicable inside the data access layer. The DAL is not the place where we define what 'a logical unit of works' i.e. 'a transaction' is. That's a decision that should be taken in the business layer, that layer doesn't own the connection. So there are reasons enough to use TransactionScope. Here's how to use TransactionScope. As you see the scope requires no access to the physical connection:

// In the Business Layer

using (System.Transactions.TransactionScope scope = new System.Transactions.TransactionScope(TransactionScopeOption.RequiresNew))

{

    // In the Data Access Layer

    using (AdventureWorks2008Entities entities = new AdventureWorks2008Entities(entitiesConnectionstring))

    {

        // Always returns 'Serializable'

        this.ErrorLabel.Content = Transaction.Current.IsolationLevel.ToString();

 

        // Your stuff here ...

    }

    scope.Complete();

}


For reasons that I don't understand, Microsoft has chosen the second worst default for TransactionScope isolation level: SERIALIZABLE. [In case you were having doubts: READ UNCOMMITTED would be the worst choice.] This means that if you don't specify a better isolation level yourself, you place a lock on everything you read, and due to lock escalation you'll probably even lock rows that you don't even read. Needless to say you'll end up with scalability issues.

Setting the isolation level in T-SQL

When starting a transaction on the connection, or when opening a TransactionScope, you can (and should) specify the appropriate isolation level. There's a third way to control the isolation level on a connection: T-SQL. This is again a low level technique that requires access to the physical data base connection. Here's an example on how to set the isolation level when using Entity Framework:

using (AdventureWorks2008Entities entities = new AdventureWorks2008Entities())

{

    entities.Connection.Open();

    entities.ExecuteStoreCommand("SET TRANSACTION ISOLATION LEVEL READ COMMITTED");

 

    // Your stuff here ...

}


The isolation level and its corresponding locking strategy will be applied to all your queries on the connection, whether or not you wrap them in a transaction. If you use this technique, you should not forget to reset the isolation level to its original value at the end of your method. Unfortunately there's no straightforward way to determine the current isolation level for a connection. [Keep reading this blog: I'm working on a solution] If you don't explicitely set the isolation level to its previous value, the new value will remain active on the connection. .NET nor SQL Server will reset it, not even when your code was called from inside a transaction!

Ignoring the isolation level

If you don't take control of it, you have no idea in which transaction isolation level your queries will be running. After all, you don't know where the connection that you got from the pool has been: it could have come from a SSIS-package doing some bulk maintenance (where SERIALIZABLE is the default), or it could been returned from an application that monitors that same SSIS-package (through a READUNCOMMITTED transaction allowing dirty reads). You simply inherit the last used isolation level on the connection, so you have no idea which type of locks are taken (or worse: ignored) by your queries and for how long these locks will be held. On a busy database, this will definitely lead to random errors, time-outs and deadlocks.

Demo

To illustrate the arbitrary isolation level, the sample application contains the following code snippet that is executed after the transaction. It executes the T-SQL version of Thread.Sleep, which gives you some time to monitor it from the outside:

using (AdventureWorks2008Entities entities = new AdventureWorks2008Entities(entitiesConnectionstring))

{

    // Script will reveal different values, depending on connection pooling

    entities.ExecuteStoreCommand("WAITFOR DELAY '00:00:10'");

}


While you run the main application, you can monitor the connections with the following SQL script:

SELECT CASE transaction_isolation_level

       WHEN 0 THEN 'Unspecified'

       WHEN 1 THEN 'Read Uncommitted'

       WHEN 2 THEN 'Read Committed'

       WHEN 3 THEN 'Repeatable Read'

       WHEN 4 THEN 'Serializable'

       WHEN 5 THEN 'Snapshot'

       ELSE 'Bazinga'

       END AS [Transaction Isolation Level]

      ,session_id AS [Session Id]

      ,login_time AS [Login Time]

  FROM sys.dm_exec_sessions

 WHERE program_name = '.Net SqlClient Data Provider'

For the record: Bazinga is not an official isolation level Tongue out.


You'll see that the isolation level for the connection is not stable:

So you should always specify an isolation level yourself. According to SQL Server Books-on-line, setting the isolation level requires a solid understanding of transaction processing theory and the semantics of the transaction itself, the concurrency issues involved, and the consequences for system consistency. I couldn't agree more.

How to detect escalation

When using TransactionScope, there's always the risk of escalation to distributed transactions. So you should keep an eye on these. There are a couple of techniques to detect and monitor distributed transactions. Here are three of them:

Component services

Via Control Panel -> Administrative Tools -> Component Services you reach the management console snap-in, that allows you to monitor MSDTC:

That same tool also alows you to configure MSDTC, and setup logging.

SQL Server Profiler

You can also trace distributed transactions with SQL Server Profiler:

Stop MSDTC and watch the exceptions in your program

Letting the application crash by stopping the MSDTC service, is my favorite solution Innocent (well, at least in the developer or test environment). The trick only works with newer versions of .NET/SQL Server. In the past, MSDTC should run even for local transactions. That bug was fixed.

Here's a way to stop MSDTC from C# (must run as administrator):

using (ServiceController sc = new ServiceController("Distributed Transaction Coordinator"))

{

    if (sc.Status == ServiceControllerStatus.Running)

    {

        sc.Stop(); // Admins only !!

    }

}


Here's the result in the test application:

Source code

Here's the full test project: U2UConsult.EF40.TransactionScope.Sample.zip (73,24 kb)

[You might want to change the AdventureWorks2008 connection strings in app.config.]

Enjoy!


Optimistic concurrency using a SQL DateTime in Entity Framework 4.0

This article explains how to implement optimistic concurrency checking using a SQL Server DateTime or DateTime2 column. It's a follow-up of my previous article on using a TimeStamp column for that same purpose. In most -if not all- concurrency checking cases it actually makes more sense to use a DateTime column instead of a TimeStamp. The DateTime data types occupy the same storage (8 bytes) as a TimeStamp, or even less: DateTime2 with 'low' precision takes only 6 bytes. On top of that: their content makes sense to the end user. Unfortunately the DateTime data types are 'a little bit' less evident to use for concurrency checking: you need to declare a trigger (or a stored procedure) on the table, and you need to hack the entity model.

A sample table

Sample time! Let's start with creating a table to hold some data.

Table definition

Here's how the table looks like (the solution at the end of the article contains a full T-SQL script). The LastModified column will be used for optimistic concurrency checking:

CREATE TABLE [dbo].[Hero](

    [Id] [int] IDENTITY(1,1) NOT NULL,

    [Name] [nvarchar](50) NOT NULL,

    [Brand] [nvarchar](50) NULL,

    [LastModified] [datetime] NULL,

 CONSTRAINT [PK_Hero] PRIMARY KEY CLUSTERED

(

    [Id] ASC

))

Trigger definition

Unlike an Identity or a TimeStamp value, a DateTime value is not automatically generated and/or updated. So we have to give the database a little help, e.g. by creating a trigger for insert and update on that table:

CREATE TRIGGER [dbo].[trg_iu_Hero]

ON [dbo].[Hero]

AFTER INSERT, UPDATE

AS

BEGIN

   SET NOCOUNT ON;

 

   UPDATE [dbo].[Hero]

      SET LastModified = GETDATE()

    WHERE Id IN (SELECT Id FROM inserted)

END


Alternatively, you could insert through a stored procedure. 

A sample application

I already prepared for you a small sample application. Here's how the main window looks like:

Cute, isn't it ?

The problem

In the entity model, you have to make sure that the LastModified column has the correct settings (Fixed and Computed):

Run the application with just the generated code. You will observe that when you update a record, the entity's LastModified property will NOT be updated. SQL Server Profiler will reveal that only an update statement is issued. The new value of LastModified is assigned by the trigger but NOT fetched:

The solution

In order to let the Entity Framework fetch the new value of the DateTime column -or whatever column that is modified by a trigger-, you need to hack the model's XML and manually add the following attribute in the SSDL:

Somewhere in Redmond there will certainly be an architect who will provide an excuse for this behavior. To us developers, this sure smells like a bug. Anyway, if you re-run the application with the modified SSDL, the new DateTime value will appear after insert or update. SQL Server profiler reveals the extra select statement:

Source Code

Here's the source code, the whole source code, and nothing but the source code: U2UConsult.EF40.DateTimeConcurrency.Sample.zip (616,27 kb)

Enjoy!

Thank you

 

This article is dedicated to my 3-year old daughter Merel. Last week she briefly turned into a real angel, but then decided to come back.

I want to thank from the bottom of my heart everybody who helped saving her life: her mama, her mammie, the MUG, and the emergency, reanimation, intensive care, and pediatric departments of the uza hospital.

 


Optimistic concurrency using a SQL Timestamp in Entity Framework 4.0

This article explains how to implement optimistic concurrency checking in the Entity Framework 4.0, using a SQL Server Timestamp column. But you could have derived that from its title.

What is a Timestamp?

Despite its name, the SQL Server Timestamp data type has nothing to do with time. DateTime2 on the other hand, is DateTime too [sorry, I couldn't resist that]. A timestamp is just an eight-bytes binary number that indicates the relative sequence in which data modifications took place in a database. The value in a column of the type Timestamp is always provided by SQL Server: it is calculated when a row is inserted, and augmented with each update to the row, to a ever increasing value that is unique in the whole database. The Timestamp data type was initially conceived for assisting in recovery operations, and you also use it to synchronize distributed databases: based on the timestamp you can detect the order in which data was added or updated, and replay a sequence of modifications. But the most common usage of timestamp is optimistic concurrency checking: when updating a row you can compare its current timestamp with the one you fetched originally. If the values are different, you know that someone else updated the row behind your back. And you know this without holding any locks on the server while you were busy, so its a very scalable solution. This type of concurrency checking is called 'optimistic': you assume that in most cases you will be able to successfully update without the need for conflict resolution.

A sample of the geeky kind

Let's create a table with such a column (the scripts-folder in the provided solution at the end of this article contains a full script):

CREATE TABLE [dbo].[FerengiRule](

    [ID] [int] NOT NULL,

    [Text] [nvarchar](100) NOT NULL,

    [Source] [nvarchar](100) NOT NULL,

    [Timestamp] [timestamp] NOT NULL,

 CONSTRAINT [PK_FerengiRule] PRIMARY KEY CLUSTERED

(

    [ID] ASC

)


Populate it with your favorite 'Ferengi Rules of Acquisition'. You find all of these here. In a WPF solution, create an entity model, and add the table to it. You see that the timestamp column has

  • Fixed as value for the Concurrency Mode property, so the column will appear in the WHERE-clause of any insert, update, or delete query, and
  • Computed as value for the StoreGeneratedPattern property, so a new value is expected from the server after insert or update.

Next, build an application with a fancy transparent startup screen, that allows you to open multiple edit windows on the same data. The startup screen could look like this:

The mainwindow of the application contains just an editable grid on the table's contents. It allows you to

  • set the concurrency resolution mode,
  • upload local modifications to the database,
  • get the current server data, and last but not least
  • restore the table to its original contents (that's an extremely useful feature in this type of application).

Here's how the window looks like:

Visualizing a Timestamp value

Just like GUIDs and technical keys, you should avoid showing timestamp values on the user interface. This demo is an exceptional to this general rule, so I built a TimestampToDouble converter to translate the eight-byte binary number to something more readable. I don't guarantee a readable output on an old active database where the timestamp value is very high, but it works fine for a demo on a fresh database:

public class SqlTimestampToDoubleConverter: IValueConverter

{

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

    {

        if (value == null)

        {

            return null;

        }

 

        byte[] bytes = value as byte[];

        double result = 0;

        double inter = 0;

        for (int i = 0; i < bytes.Length; i++)

        {

            inter = System.Convert.ToDouble(bytes[i]);

            inter = inter * Math.Pow(2, ((7 - i) * 8));

            result += inter;

        }

        return result;

    }

 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

    {

        throw new NotImplementedException();

    }

}

 

Concurrency

Generated SQL Queries

If you run your SQL Profiler while modifying data through via the main window, you'll see that the Entity Framework query's WHERE-clause contains the timestamp, and that after the update the new value is fetched for you:

If there's no row to be updated, then someone else must have modified (or deleted) it. You can test that very easily with the sample application by opening multiple edit windows and playing around with the data.

Client side conflict resolution

When the entity framework discovers a concurrency violation when saving your changes, it appropriately throws an OptimisticConcurrencyException. It's then time for you to solve the conflict. In most cases, that means fetching the current values, sending these to the GUI, and let the end user decide what should happen. The data access layer code for inserts and updates will look like this:

foreach (var rule in this.rules)

{

    try

    {

        switch (rule.ChangeTracker.State)

        {

            case ObjectState.Added:

                entities.FerengiRules.AddObject(rule);

                entities.SaveChanges();

                break;

            case ObjectState.Modified:

                entities.FerengiRules.ApplyChanges(rule);

                entities.SaveChanges();

                break;

            default:

                break;

        }

    }

    catch (OptimisticConcurrencyException)

    {

        // Return Current Values

        // ...

    }

}

 

Server side conflict resolution

The Entity Framework also provides automated conflict resolution strategies that might be useful in some scenarios (although to be honest: I can't think of any). There's a Refresh method that you can use to decide whether it's the client version or the server (store) version that should be persisted when there's a conflict. Here's how the catch-block could look like:

catch (OptimisticConcurrencyException)

{

    switch (this.conflictResolution)

    {

        case ConflictResolution.Default:

            throw;

        case ConflictResolution.ServerWins:

            entities.Refresh(RefreshMode.StoreWins, rule);

            entities.SaveChanges();

            break;

        case ConflictResolution.ClientWins:

            entities.Refresh(RefreshMode.ClientWins, rule);

            entities.SaveChanges();

            break;

        default:

            break;

    }

}

 

Source Code

Oops ... almost forgot: here's the source code of the whole thing: U2UConsult.EF40.OptimisticConcurrency.Sample.zip (470,96 kb)

Enjoy!


Globalizing and Localizing a WPF application

This article describes how to localize a WPF application using the WPF Localization Extension project from Codeplex. On one hand, this is a fine tool. On the other hand, it's a crying shame that WPF developers need to rely on external sources for something as basic as localization. As you know, localization support is nicely integrated in Microsoft's other development stacks, like WinForms and ASP.NET. So far for the ranting, let's get to the solution.

Terminology

Globalization is making your application ready to be localized. This boils down to separating culture-specific elements (texts, images, colors, ...) from the code. The globalization code analysis rules may help you to do this.

Localization is tailoring your application toward a specific language and region by providing these culture-specific elements (e.g. in a resource file or a database).

Options for WPF localization

These are a couple of options for localizing a WPF application:

  • use the clumsy and error prone LocBaml tool. Don't get me wrong: I really like the idea of skipping the globalization step and then do localization as an afterthought. But just read the intro of this article for a list of reasons NOT to use LocBaml,
  • use classic RESX files, or
  • use WPF ResourceDictionaries.

More details about the pros and cons of these alternatives can be found here.

The WPF Localization Extension project

The WPF Localization Extension allows you to localize your application using classic .resx files. The project revolves around a custom markup extension that allows you to declaratively (in XAML) bind control properties to localized resources. The library offers a lot of functionality, but more important: it is well-written and well-documented (at least in its source code). I built a small sample application that walks through some of its features. Here's how this application looks like. You find its source code at the end of this article:

The project is decorated with the following resource files: 

Declarative Localization

The markup extension and its namespaces are registered by the following declaration on top your XAML file (you might want to change the project's source code to choose a more appropriate namespace):

xmlns:lex="http://schemas.root- project.org/xaml/presentation"


You can now set up a binding from a control's property to a resource, like this:

<TextBlock Text="{lex:LocText Key=Tomato, Dict=Translations, Assembly=U2UConsult.WPF.Localization.Sample}" />


It's possible to ignore the current culture, and force a specific culture for a binding, like this:

<TextBlock Text="{lex:LocText Key=Duck, Dict=Translations, Assembly=U2UConsult.WPF.Localization.Sample, ForceCulture=nl}" />


My sample application only fetches string resources, but WPF Localization Extension> supports the following resource types out of the box:

  • Brush,
  • Double,
  • FlowDirection,
  • Image,
  • Text, and
  • Thickness.

For other data types you'll need to plug in a Converter.

Programmatic Localization

Sometimes we need to localize a control in source code, e.g. when the control is dynamically created. In this case we can set the binding programmatically, like this:

LocTextExtension loc = new LocTextExtension("U2UConsult.WPF.Localization.Sample:Translations:Pumpkin");

loc.SetBinding(this.PumpkinTextBlock, TextBlock.TextProperty);


If data binding is not needed (or not possible), the you can fallback to a lookup in the .resx file using GetLocalizedObject, like this:

string pinguin = LocalizeDictionary.Instance.GetLocalizedObject<string>(

    "U2UConsult.WPF.Localization.Sample",

    "Translations",

    "Pinguin",

    CultureInfo.GetCultureInfo("nl-BE"));

this.PinguinTextBlock.Text = pinguin;

 

Design time support

Localization at run time is one thing, but as a developer we like to see the result without running the application. The LocalizeDictionary.DesignCulture dependency property provides a Culture for Visual Studio's designers. It can be set in XAML, as follows:

lex:LocalizeDictionary.DesignCulture="nl-BE"


[By the way: the design time support only started working on my VS2010 after I recompiled the codeplex source with VS2010.]

On top of that, the markup extension provides a DesignValue property that sets the value in Visual Studio's Designer, regardless of the (Design-)Culture. Here's a sample:

<TextBlock Text="{lex:LocText Key=Tomato, Dict=Translations, Assembly=U2UConsult.WPF.Localization.Sample, DesignValue=#Tomato#}" />


Here's how these two features look like at design time:

Finally, the markup extension also provides a InitialValue for Blend support.

Missing cultures and missing translations

I guess we all agree that our application should never totally crash if a string can not be found in a resource file, or if the user has an unexpected or unsupported locale. Here are some techniques to get around this.

Missing resources

It's not a good idea to just fallback to a default language for missing entries, without a warning to the end user. In the best case this will only create confusion. But just take a look at the following interlingual homographs and consider what would happen if they appear in the middle of a half-translated window:

  • coin is french for corner,
  • file is dutch for traffic jam, and
  • gift is german for poison

So the invariant culture should NOT be English (or whatever 'real' language), but still remain comprehensible. In my app, the invariant resource file looks like this:

When a translation (or the whole culture) falls back to the invariant culture, the user interface looks like this (Tomato and Pumpkin are not translated):

Missing cultures

If a specific culture is not found (e.g. 'fr-NL') then it makes sense to first check if the language exists ('fr'), and only use the invariant culture as a last resort. That's exactly what the following code does. The 'French' and 'Dzongkha' buttons in the sample application test all code paths:

private void SwitchCulture(string culture)

{

    CultureInfo ci = CultureInfo.InvariantCulture;

    try

    {

        ci = new CultureInfo(culture);

    }

    catch (CultureNotFoundException)

    {

        try

        {

            // Try language without region

            ci = new CultureInfo(culture.Substring(0, 2));

        }

        catch (Exception)

        {

            ci = CultureInfo.InvariantCulture;

        }

    }

    finally

    {

        LocalizeDictionary.Instance.Culture = ci;

        this.CultureTextBlock.Text = ci.EnglishName;

    }

}

 

Source code

Last but not least, here's the source code of the small sample project: U2UConsult.WPF.Localization.Sample.zip (2,41 mb)

Enjoy!


Self-Tracking Entities with Validation and Tracking State Change Notification

This article explains how to extend Self-Tracking Entities (STE) from Entity Framework (EF) 4.0 with validation logic and (tracking) state change notification, with just minimal impact on the T4 files. We'll build a two-tier application that submits local changes in a WPF application via a WCF service to a database table. The STE are extended with validation logic that is reusable on client and server. The client is notified when the change tracker of an entity changes its state. The tracking state is displayed to the end user as an icon. Here's the client application in action:

For more details on the foundations of building N-Tier apps with EF 4.0, please read Peter Himschoots article.

Source Code

For the fans of the source-code-first approach, here it is: U2UConsult.SelfTrackingEntities.Sample.zip (622,23 kb)

The structure of the solution is as follows:

Preparation

Database table

First you need a SQL Server table. The provided source code contains a script to generate a working copy of the SalesReason table in the AdventureWorks2008 sample database. This is its initial content:

Data Access Layer

When you have it, it's time to fire up Visual Studio.NET. Create a WCF web service project with an ADO.NET Entity Model. Add the SalesReason2 table to the model (I renamed the entity and entity set to SalesReason and SalesReasons respectively). While you're in the designer, generate the code for the ObjectContext and the Self-Tracking Entities (right click in the designer, select "Add Code Generation Item", select "ADO.NET Self-Tracking Entity Generator"). Add the canonical service methods to fetch the full list of SalesReasons, and to add, delete, and update an individual SalesReason. Here's an example (I personally like to combine Add and Update operations in a Save method):

public List<SalesReason> GetSalesReasons()

{

    using (AdventureWorks2008Entities model = new AdventureWorks2008Entities())

    {

        List<SalesReason> result = new List<SalesReason>();

        result.AddRange(model.SalesReasons);

        return result;

    }

}

 

public void DeleteSalesReason(SalesReason reason)

{

    using (AdventureWorks2008Entities model = new AdventureWorks2008Entities())

    {

        model.SalesReasons.Attach(reason);

        model.SalesReasons.DeleteObject(reason);

        model.SaveChanges();

    }

}

 

public SalesReason SaveSalesReason(SalesReason reason)

{

    using (AdventureWorks2008Entities model = new AdventureWorks2008Entities())

    {

        reason.ModifiedDate = DateTime.Now;

        if (reason.ChangeTracker.State == ObjectState.Added)

        {

            model.SalesReasons.AddObject(reason);

            model.SaveChanges();

            reason.AcceptChanges();

            return reason;

        }

        else if (reason.ChangeTracker.State == ObjectState.Modified)

        {

            model.SalesReasons.ApplyChanges(reason);

            model.SaveChanges();

            return reason;

        }

        else

        {

            return null; // or an exception

        }

    }

}

 

Self Tracking Entities

Add a new class library to the project, call it STE. Drag the Model.tt T4 template from the DAL to the STE project. Add a reference to serialization in the STE project. Add a reference to the STE in the DAL project. Everything should compile again now.

WPF Client

Add a WPF application to the solution. In this client project, add a reference to the STE, and a service reference to the DAL. Add a ListBox and some buttons, with straightforward code behind:

private void RefreshSalesReasons()

{

    this.salesReasons = this.GetSalesReasons();

 

    this.SalesReasonsListBox.ItemsSource = this.salesReasons;

}

 

private ObservableCollection<SalesReason> GetSalesReasons()

{

    using (DAL.SalesReasonServiceClient client = new DAL.SalesReasonServiceClient())

    {

        ObservableCollection<SalesReason> result = new ObservableCollection<SalesReason>();

        foreach (var item in client.GetSalesReasons())

        {

            result.Add(item);

        }

 

        return result;

    }

}

 

private void Update_Click(object sender, RoutedEventArgs e)

{

    SalesReason reason = this.SalesReasonsListBox.SelectedItem as SalesReason;

    if (reason != null)

    {

        reason.Name += " (updated)";

    }

}

 

private void Insert_Click(object sender, RoutedEventArgs e)

{

    SalesReason reason = new SalesReason()

    {

        Name = "Inserted Reason",

        ReasonType = "Promotion"

    };

    reason.MarkAsAdded();

 

    this.salesReasons.Add(reason);

 

    this.SalesReasonsListBox.ScrollIntoView(reason);

}

 

private void Delete_Click(object sender, RoutedEventArgs e)

{

    SalesReason reason = this.SalesReasonsListBox.SelectedItem as SalesReason;

    if (reason != null)

    {

        reason.MarkAsDeleted();

    }

}

 

private void Commit_Click(object sender, RoutedEventArgs e)

{

    using (DAL.SalesReasonServiceClient client = new DAL.SalesReasonServiceClient())

    {

        foreach (var item in this.salesReasons)

        {

            switch (item.ChangeTracker.State)

            {

                case ObjectState.Unchanged:

                    break;

                case ObjectState.Added:

                    client.SaveSalesReason(item);

                    break;

                case ObjectState.Modified:

                    client.SaveSalesReason(item);

                    break;

                case ObjectState.Deleted:

                    client.DeleteSalesReason(item);

                    break;

                default:

                    break;

            }

        }

 

        this.RefreshSalesReasons();

    }

}


Now you're ready to extend the STE with some extra functionality.

Validation

It's nice to have some business rules that may be checked on the client (to provide immediate feedback to the user) as well as on the server (to prevent corrupt data in the database). This can be accomplished by letting the self-tracking entities implement the IDataErrorInfo interface. This interface just contains an indexer (this[]) to validate an individual property, and an Error property that returns the validation state of the whole instance. Letting the STE implement this interface can be easily done by adding a partial class file. The following example lets the entity complain if its name gets shorter than 5 characters:

public partial class SalesReason : IDataErrorInfo

{

    public string Error

    {

        get

        {

            return this["Name"];

        }

    }

 

    public string this[string columnName]

    {

        get

        {

            if (columnName == "Name")

            {

                if (string.IsNullOrWhiteSpace(this.Name) || this.Name.Length < 5)

                {

                    return "Name should have at least 5 characters.";

                }

            }

 

            return string.Empty;

        }

    }

}


If you add a data template to the XAML with ValidatesOnDataErrors=true in the binding, then the GUI will respond immediately if a business rule is broken.

XAML:

<TextBox

   Width="180"

   Margin="0 0 10 0">

    <Binding

       Path="Name"

       Mode="TwoWay"

       UpdateSourceTrigger="PropertyChanged"

       NotifyOnSourceUpdated="True"

       NotifyOnTargetUpdated="True"

       ValidatesOnDataErrors="True"

       ValidatesOnExceptions="True"/>

</TextBox>


Result:

The same rule can also be checked on the server side, to prevent persisting invalid data in the underlying table:

public SalesReason SaveSalesReason(SalesReason reason)

{

    if (!string.IsNullOrEmpty(reason.Error))

    {

        return null; // or an exception

    }

 

    ...

 

Notification of Tracking State Change

By default, an STE's tracking state can be fetched by instance.ChangeTracker.State. This is NOT a dependency property, and its setter doesn't call PropertyChanged. Clients can hook an event handler to the ObjectStateChanging event that is raised just before the state changes (there is no ObjectStateChanged event out of the box). You're free to register even handlers in your client, but then you need to continuously keep track of which change tracker belongs to which entity: assignment, lazy loading, and (de)serialization will make this a cumbersome and error prone endeavour.

To me, it seems more logical that an entity would expose its state as a direct property, with change notification through INotifyPropertyChanged. This can be achieved -again- by adding a partial class file:

public partial class SalesReason

{

    private string trackingState;

 

    [DataMember]

    public string TrackingState

    {

        get

        {

            return this.trackingState;

        }

 

        set

        {

            if (this.trackingState != value)

            {

                this.trackingState = value;

                this.OnTrackingStateChanged();

            }

        }

    }

 

    partial void SetTrackingState(string newTrackingState)

    {

        this.TrackingState = newTrackingState;

    }

 

    protected virtual void OnTrackingStateChanged()

    {

        if (_propertyChanged != null)

        {

            _propertyChanged(this, new PropertyChangedEventArgs("TrackingState"));

        }

    }

}


The only thing you need to do now, is to make sure that the SetTrackingState method is called at the right moment. The end of the HandleObjectStateChanging looks like a nice candidate. Unfortunately this requires a modification of the code that was generated by the T4 template. For performance reasons I used a partial method for this. This is the extract from the SalesReason.cs file:

// This is a new definition

partial void SetTrackingState(string trackingState);

//

 

private void HandleObjectStateChanging(object sender, ObjectStateChangingEventArgs e)

{

    //

    this.SetTrackingState(e.NewState.ToString()); // This is a new line

    //

 

    if (e.NewState == ObjectState.Deleted)

    {

        ClearNavigationProperties();

    }

}


Just modifiying the generated code is probably not good enough: if later on you need to update your STE (e.g. after adding a column to the underlying table), the modifications will get overriden again. So you might want to modify the source code of the T4 template (search for the HandleObjectStateChanding method and adapt the source code). Fortunately this is a no-brainer: most of the T4 template is just like a C# source code file, but without IntelliSense. The rest of the file looks more like classic ASP - ugh.

Anyway, you end up with a TrackingStatus property to which you can bind user interface elements, wiith or without a converter in between. In the sample application I bound an image to the tracking state:

<Image

   Source="{Binding

       Path=TrackingState,

       Converter={StaticResource ImageConverter}}"

   Width="24" Height="24" />


Here's how it looks like:

In general, I think there are not enough partial methods defined and called in the Entity Framework T4 templates. To be frank: 'not enough' is an understatement: I didn't find a single partial method.


WPF 4.0 and Windows 7: get more Functionality per Square Inch

The Windows 7 taskbar comes with nice features like a thumbnail preview with clickable thumb buttons, a progress bar in the taskbar item, and jump list items and task items in its context menu. Access to the shell integration API from the managed world is done through the System.Windows.Shell namespace that comes with .NET 4.0. This namespace decorates Window and Application with some new dependency properties, so you better make use of it.

Here's an overview of the TaskbarItemIfo object model:

The screenshot comes from a small application to demonstrate this object model. Here's how the main form looks like:

The Chart and Pie buttons switch the displayed chart type, the Recalculate button simulates a long running operation (just an excuse for showing the progress bar). Here's the alternative view:

TaskBarItemInfo

When hovering with the mouse over the taskbar item, it shows only the relevant part of the screen in its thumbnail, and operational buttons - just like in the first image above.

Everything is defined in the xaml as follows:

<Window.TaskbarItemInfo>

    <TaskbarItemInfo

       x:Name="taskBarItemInfo1"

       ThumbnailClipMargin="5 95 100 65"

       Description="Taskbar Item Info Sample">

        <TaskbarItemInfo.ThumbButtonInfos>

            <ThumbButtonInfoCollection>

                <ThumbButtonInfo

                   Click="Recalculate_Click"

                   Description="Recalculate"

                   ImageSource="/Assets/Images/refresh.png" />

                <ThumbButtonInfo

                   Click="BarChart_Click"

                   Description="Bar Chart"

                   ImageSource="/Assets/Images/chart.png" />

                <ThumbButtonInfo

                   Click="Pie_Click"

                   Description="Pie Chart"

                   ImageSource="/Assets/Images/pie.png"/>

            </ThumbButtonInfoCollection>

        </TaskbarItemInfo.ThumbButtonInfos>

    </TaskbarItemInfo>

</Window.TaskbarItemInfo>


I hooked the thumb buttons to the same click event as their counterparts on the main form, but everything also works with command bindings. In fact, the taskbar item has more FSI than the original app, that's Functionality per Square Inch.

Overlay

The taskbar icon can be decorated with an extra image to inform the user about the state of the application. This overlay image can be set in XAML (through data binding, if you want), but in a lot of cases you'll want to change the image from source code. Here's how this is done:

this.taskBarItemInfo1.Overlay = new BitmapImage(

    new Uri(

        @"..\..\Assets\Images\pie.png",

        UriKind.Relative));

 

ProgressBar

The task bar item can be decorated with a progress bar. This is how it's done from C#:

this.taskBarItemInfo1.ProgressState = TaskbarItemProgressState.Normal;

for (double d = 0; d < 80; d++)

{

    this.taskBarItemInfo1.ProgressValue = d / 100;

    Thread.Sleep(50);

}

this.taskBarItemInfo1.ProgressState = TaskbarItemProgressState.Paused;

Thread.Sleep(2000);

this.taskBarItemInfo1.ProgressState = TaskbarItemProgressState.Error;

for (double d = 80; d > 0; d--)

{

    this.taskBarItemInfo1.ProgressValue = d / 100;

    Thread.Sleep(50);

}

this.taskBarItemInfo1.ProgressState = TaskbarItemProgressState.None;


Here's the progress bar in action:

ProgressValue is a value between 0 and 1, while ProgressState is one of the following:

  • None: well - no progress bar,
  • Normal: a green bar,
  • Paused: a yellow bar,
  • Error: a red bar,
  • Indeteminate: a zigzagging green bar (very nice in combination with a wait cursor on the form)

Source Code

As always you get the full source code (VS 2010): U2UConsult.Windows7.Sample.zip (864,23 kb)

Enjoy!


WCF Data Services 4.0 in less than 5 minutes

WCF Data Services 4.0 (formerly known as ADO.NET Data Services, formerly known as Astoria) is one of the ways to expose an Entity Data Model from Entity Framework 4.0 in a RESTful / OData way. This article explains how to create such a data service and how to consume it with a browser and with a WPF client.

The Data Service

Start with an empty ASP.NET Application:

Add a WCF Data Service to it:

Also add an Entity Data Model to the ASP.NET project:

Follow the Model Wizard to create a model containing entities on top of the Employee and Person tables from the AdventureWorks2008 database:

In the designer, you should have something like this:

A lot of code was generated, let's add our own 50ct in the service's code behind. First let it inherit from DataService<AdventureWorks2008Entities>:

public class WcfDataService : DataService<AdventureWorks2008Entities>

{ .. }

 

Then modify the InitializeService method as follows. This exposes all operations and grants all access rights (not really a production setting):

public static void InitializeService(DataServiceConfiguration config)

{

    config.SetEntitySetAccessRule("*", EntitySetRights.All);

    config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);

    config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;

}


Believe it or not, we're done (for the first part): the entity model is now exposed in a RESTful way. At the root URL you get an overview of the exposed entities. In the attached sample the root URL is "http://localhost:1544/WcfDataService.svc", but you may of course end up with another port number:

At the "/Employees" address you find all employees:

In your browser this list of employees may appear like this:

This means it's time to -at least temporarily- disable your rss feed reading view. Here's how to do this in IE:

 

 

To reach an individual entity, just type its primary key value in parentheses at the end of the URL, like "http://localhost:1544/WcFDataService.svc/Employees(1)":

You can navigate via the relationships between entities. This is how to reach the Person entity, connected to the first Employee. The URL is "http://localhost:1544/WcfDataService.svc/Employees(1)/Person":

Other OData URI options options can be found here, including:

  • Filtering: http://localhost:1544/WcfDataService.svc/Employees?$filter=JobTitle eq 'Chief Executive Officer'
  • Projection: http://localhost:1544/WcfDataService.svc/Employees?$select=JobTitle,Gender
  • Client side paging: http://localhost:1544/WcfDataService.svc/Employees?$skip=5&$top=2

Version 4.0 also includes support for server side paging. This gives you some control over the resources. Add the following line in the InitializeService method:

config.SetEntitySetPageSize("Employees", 3);


Only 3 employees will be returned now, even if the client requested all:

A Client

Enough XML for now. WCF Data Services also expose a client side model that allows you to use LINQ.

Create a new WPF application:

Add a Service Reference to the WFC Data Service:

Decorate the Window with two buttons and a listbox. It should look more or less like this:

The ListBox will display Employee entities through a data template (OK, that's XML again):

<ListBox

   Name="employeesListBox"

   ItemTemplate="{StaticResource EmployeeTemplate}"

   Margin="4"

   Grid.Row="1"/>


Here's the template. It not only binds to Employee properties, but also to Person attributes:

<DataTemplate

   x:Key="EmployeeTemplate">

    <StackPanel>

        <StackPanel Orientation="Horizontal">

            <TextBlock

               Text="{Binding Path=Person.FirstName}"

               FontWeight="Bold"

               Padding="0 0 2 0"/>

            <TextBlock

               Text="{Binding Path=Person.LastName}"

               FontWeight="Bold"/>

        </StackPanel>

        <StackPanel Orientation="Horizontal">

            <TextBlock

               Text="{Binding Path=JobTitle}"

               Width="180"/>

            <TextBlock

               Text="{Binding Path=VacationHours}"

               Width="60"

               TextAlignment="Right" />

            <TextBlock

               Text=" vacation hours taken." />

        </StackPanel>

    </StackPanel>

</DataTemplate>


The Populate-Button fetches some Employee entities together with their related Person entity, and binds the collection to the ListBox (in version 4.0 two-way bindings are supported for WPF):

private void Populate_Click(object sender, RoutedEventArgs e)

{

    AdventureWorks2008Entities svc =

        new AdventureWorks2008Entities(

            new Uri("http://localhost:1544/WcfDataService.svc"));

 

    this.employeesListBox.ItemsSource =

        svc.Employees.Expand("Person").Where(emp => emp.BusinessEntityID < 100);

}


Here's the result:

The Update-Button updates the number of vacation hours of the company's CEO. It fetches the Employee, updates its VacationHours property, then tells the state manager to update the employee's state, and eventually persists the data:

private void Update_Click(object sender, RoutedEventArgs e)

{

    AdventureWorks2008Entities svc =

        new AdventureWorks2008Entities(

            new Uri("http://localhost:1544/WcfDataService.svc"));

 

    Employee employee =

        svc.Employees.Where(emp => emp.BusinessEntityID == 1).First();

 

    employee.VacationHours++;

 

    svc.UpdateObject(employee);

    svc.SaveChanges();

}


If you now repopulate the listbox, you will see the increased value:

Source Code

Here's the full source code of this sample (just requires VS2010 with no extra downloads): U2UConsult.WcfDataServices.Sample.zip (96,59 kb)

Enjoy!


PRISM in 600 seconds

Welcome to the lean, mean, no Vicodin, U2U Consult PRISM machine. (595 seconds left.) CompositeWPF, or Composite Application Guidance (CAG) including Composite Application Library (CAL) is still commonly referred to as PRISM. The software component -CAL- extends Windows Presentation Foundation (WPF) with Modularity, Dependency Injection, Loosely Coupled Events, Distributed Commanding, and Run-Time Module Discovery, while leveraging the classic WPF principles and design concepts such as Dependency Properties, Routed Events, Commanding, Data Binding and Data Templates. In a composite application, functionality is embedded in small parts called modules. Each module is an autonomous, dynamically discoverable and loadable piece, containing its own view, logic and services. A module is preferably designed and implemented according to the MVP-pattern. The main application contains one or more shells: empty windows with regions that contain the placeholders for the module's views. This article walks through a small sample CAL-based solution. Here's how the GUI looks like, in sober black and white:

 

If you would build it as a single monolithic application, it would take you 10 minutes to develop. The  CAL-based implementation is actually composed of 6 (six) independent projects with hardly any references to one another:

And now 10 minutes is maybe even too long to explain how everything works. Anyway, I'm going to give it a try!

Shells and Regions

A Composite WPF application starts as a regular WPF application with references to all of the CAL-assemblies (the ones starting with Microsoft in the next screen shot):

The CompositeWPF namespace is imported into the XAML of the Main Window:

xmlns:cal="http://www.codeplex.com/CompositeWPF"


Regions are added in the XAML by creating ItemControl and ContentControl instances with a RegionName. This dependency property exposes the region's name to CAL's region manager:

<ItemsControl

   x:Name="MainRegion"

   cal:RegionManager.RegionName="MainRegion" />

 

Modules and Dependency Injection

The AboutModule is kind of a "Hello World" module: it just statically displays some company's logo. A module generally doesn't need to call the whole CAL-shebang, so it can get away with less references:

The module itself is a class that implements the IModule interface. It is decorated with the Module atttribute to allow dynamic discovery:

[Module(ModuleName = "AboutModule")]

public class AboutModule : IModule

{

    // ...

}


The graphical part of the module is implemented as a WPF UserControl and saved in a Views subfolder. It needs no special references or interfaces:

The IRegionManager parameter in the module's constructor will be discovered and populated by CAL's Dependency Injection Container (Unity, that is). It gives the module and the view access to the shell's region manager:

public AboutModule(IRegionManager regionManager)

{

    this.regionManager = regionManager;

}

 

CAL will call the module's constructor, and then its Initialize method, where the view is registered in the named region:

public void Initialize()

{

    this.regionManager.RegisterViewWithRegion(

        "MainRegion",

        typeof(Views.U2UConsultLogo));

}

 

Bootstrapping the Application

The main project contains a bootstrapper. It makes sure that CAL's components are properly initialized before anything else happens:

internal class Bootstrapper : UnityBootstrapper

{

    // ...

}

 

The OnStartUp of the application is overridden:

protected override void OnStartup(StartupEventArgs e)

{

    base.OnStartup(e);

 

    Bootstrapper bootstrapper = new Bootstrapper();

    bootstrapper.Run();

}

 

Since the bootstrapper will do the initialization, the StartupUri is removed from app.xaml:

<Application x:Class="U2UConsult.CAL.Sample.App"

   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <!--StartupUri="Shell.xaml"-->

</Application>

 

Back in the bootstrapper, the CreateShell() method is overridden to make sure that the shell gets loaded and displayed:

protected override DependencyObject CreateShell()

{

    Shell shell = new Shell();

    shell.Show();

    return shell;

}

 

The GetModuleCatalog() method is also overridden. It returns the collection of discovered modules. There are different types of module catalog subclasses that can inspect directories, configuration files, or even XAML files. The following code is an example of using the ModuleCatalog base class itself. This way of statically loading modules requires a reference from the shell project to the module project(s), so it's only used while developing/debugging:

protected override IModuleCatalog GetModuleCatalog()

{

    ModuleCatalog catalog = new ModuleCatalog();

    catalog.AddModule(typeof(AboutModule.AboutModule));

    return catalog;

}

 

Model View Presenter

The region at the bottom of the main window's shell displays the application's status. XAML-wise it's just a textblock. When it is is implemented using a (lightweight) MVP-pattern and packaged as a CAL module, it looks rather impressive:

The view contains a textblock which is bound to a property in the PresentationModel:

<TextBlock

   TextWrapping="NoWrap"

   Text="{Binding StatusMessage}"/>

 

The StatusModule requires more of the CAL feature set than the AboutModule, so it has more injected stuff (i.e. parameters in its constructor):

public StatusModule(

    IUnityContainer container,

    IRegionManager regionManager,

    IEventAggregator eventAggregator)

{

    this.container = container;

    this.regionManager = regionManager;

    this.eventAggregator = eventAggregator;

}

 

The registration of the views and services that are provided by the module, is nicely factored out to a seperate method:

public void RegisterViewsAndServices()

{

    this.container.RegisterType<Views.IStatusView, Views.StatusView>(

        new ContainerControlledLifetimeManager());

    this.container.RegisterType<PresentationModels.IStatusPresentationModel, PresentationModels.StatusPresentationModel>(

        new ContainerControlledLifetimeManager());

}

 

And here's the module's Initialize-method:

public void Initialize()

{

    this.RegisterViewsAndServices();

 

    PresentationModels.IStatusPresentationModel model =

        this.container.Resolve<PresentationModels.StatusPresentationModel>();

    IRegion statusRegion = this.regionManager.Regions["StatusRegion"];

    statusRegion.Add(model.View);

}

 

The PresentationModel gets its view from Dependency Injection, again through a parameter in its constructor. So here's where the model and its view are connected:

public StatusPresentationModel(Views.IStatusView view)

{

    this.view = view;

    view.Model = this;

 

    this.StatusMessage = "The status module is operational.";

}

 

Distributed Events

The SelectionModule allows the end user to select an option, after which it will update the application's status. This status is displayed in the status region at the bottom of the shell:

Some corners were cut here: the project only contains a Module and a View. Anyway, the SelectionModule needs to communicate with the StatusModule. Both modules share an event -an instance of CompositePresentationEvent- through CAL's event aggregator, a mechanism for distributed events. The reference to this event aggregator comes from ... Dependency Injection indeed: the constructors of SelectionModule, SelectionView, StatusModule, and StatusPresentationModel take an IEventAggrator parameter.

A global StatusReported event is declared in the application. The SelectionModule raises this event via a call to Publish():

private void RadioButton_Checked(object sender, RoutedEventArgs e)

{

    this.selectedOption = e.Source as RadioButton;

 

    string status = string.Format(

        "You selected '{0}'.",

        this.selectedOption.Content.ToString());

 

    this.eventAggregator.GetEvent<Infrastructure.StatusReportedEvent>().Publish(status);

}

 

The StatusModule has a local event handler for the same event:

private void OnAppStatusChanged(string message)

{

    this.StatusMessage = message;

}

 

It registers that handler with CAL through a Subscribe-call:

this.eventAggregator.GetEvent<Infrastructure.StatusReportedEvent>()

     .Subscribe(this.OnAppStatusChanged, ThreadOption.UIThread, true);

 

The handler itself is straightforward - data binding will update the view:

private void OnAppStatusChanged(string message)

{

    this.StatusMessage = message;

}

 

As you observed, the reference to the event is not by name (like for a region), but it is made by type. Both modules, as well as all other modules that want to notify status changes, need to know the event type:

public class StatusReportedEvent : CompositePresentationEvent<string> { }


The type is defined is a so-called Infrastructure project to which multiple modules -and probably even the shell- will have a reference. To call a spade a bloody shovel: GlobalVariables would be a more appropriate name for this assembly. But that name seems to upset software architects.

Composite Commands

In WPF we like to communicate through Commands, not Events. So here's the next use case. The shell has a toolbar region on top. This will host the toolbar buttons of each individual module, but also some global commands. A global "Clear" button clears any registered view, and updates the status:

The global command itself is an instance of CAL's CompositeCommand class - a command that can have child commands. It is defined in the Infrastructure project, together with a proxy to it that can be overridden for unit testing:

namespace Infrastructure

{

    using Microsoft.Practices.Composite.Presentation.Commands;

 

    public static class GlobalCommands

    {

        public static CompositeCommand ClearCommand = new CompositeCommand();

    }

 

    public class ClearCommandProxy

    {

        public virtual CompositeCommand ClearCommand

        {

            get

            {

                return GlobalCommands.ClearCommand;

            }

        }

    }

}


The button with the large "X" is linked to the global command through its XAML:

<UserControl

   x:Class="GlobalCommandsModule.Views.SelectionCommandView"

   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   xmlns:inf="clr-namespace:Infrastructure;assembly=Infrastructure" >

    <Button Command="{x:Static inf:GlobalCommands.ClearCommand}" ... />

</UserControl>


When the SelectionView is loaded, it hooks a DelegateCommand to the global ClearCommand:

public SelectionView(

    IEventAggregator eventAggregator,

    ClearCommandProxy commandProxy)

{

    InitializeComponent();

 

    this.eventAggregator = eventAggregator;

 

    this.clearCommand = new DelegateCommand<object>(this.Clear, this.CanClear);

    commandProxy.ClearCommand.RegisterCommand(this.clearCommand);

}


DelegateCommand is yet another CAL-class. It lets you directly specify the ICommand-code for Execute and CanExecute as delegates.

Dynamic Module Lookup

During development it makes sense to keep a reference from the host application to each module, and load it statically into the module catalog. At the end of the day, it's better to cut that reference and go for dynamic lookup. So all modules are compiled and their dll's gathered in a "Modules"-folder:

 

The "production"-bootstrapper makes use of one of the more specialized catalog modules:

protected override IModuleCatalog GetModuleCatalog()

{

    DirectoryModuleCatalog catalog = new DirectoryModuleCatalog();

    catalog.ModulePath = "../../Modules";

 

    return catalog;

}

 

Source Code

Here's the full source code of the sample application: U2UConsult.CAL.Sample.zip (1,79 mb)

Enjoy!