Pages

Monday, April 22, 2013

Set UpdateCheck to Never programatically for LINQ Data Contexts

By default when you generate a LINQ Data Context in Visual Studio, every column of every table has the UpdateCheck property set to Always. The implication of this is that the UPDATE sql statements issued by LINQ will include all the fields in the WHERE clause in order to match the exact copy of the record that was initially read and prevent overwriting changes made by other users/threads between the last time we read the record and the moment we try to update it. And that's fine in many scenarios but sometimes you want all the UPDATE statements to find the record to update and change it regardless of changes sent by others (a "last commit wins" type of policy) and for that you'd need LINQ's UPDATE statements to only include the table's primary key fields in the WHERE clause. That is, you need the UpdateCheck property set to Never for all the columns that are not primary keys.

Certainly one way to accomplish this is by clicking all the desired columns in the designer view and setting the property to Never manually. Although this solves the problem, it becomes too much work when the number of tables and columns grows. Also if you happen to regenerate the LINQ context somewhere down the development cycle, you lose all those manual customizations previously made and the new LINQ context generated will need to have the same manual work done.

Ideally you want to find a way to customize this programatically but unfortunately there are no properties to do it easily and I couldn't find any documentation on the Internet on how to do it.

So, our team had to get their hands dirty and we had to use reflection techniques. We created our own Custom LINQ Context object (called DiamondDataWriterContext) which inherits from the standard LINQ Data Context created via the designer, and in its constructor a method is invoked that loops through all the tables and sets the UpdateCheck  = Never for all the columns that are not primary keys:



And then the chicken: The implementation of the SetUpdateChecks() method:



  Finally a utility method used above which has been re-factored into a small reusable function:



If you are accessing the Data base with Entity Framework you don't have to do this with Reflection as you have way more control over your objects via more public members exposed by the framework. But sometimes, you just can't migrate your data access technology just like that when a huge, tested system, already exists that provides clients with a reliable service (specially in the financial industry).

A final word of caution: creating an instance of this LINQ Context object at run time obviously takes longer than the Out of the box LINQ Dtaa Context offered by the .NET frameworl. But the latency can still be a manageable performance decrease in your case. In my particular project (118 tables in the database) the Context gets created in 0.03 seconds, so not too bad although definitely much slower than the average 0.000025 seconds that the standard version takes to be instantiated.

Hope it helps someone out there.


No comments:

Post a Comment