Ran across a small issue with LINQ TO SQL I'd like to share. As you may or may not know LINQ TO SQL's default behavior when retrieving a result set from the database for an entity is to keep that object in cache. If you run another query against linq attempting to retrieve the same row, LINQ will return the cached object. Depending on how you want your program to behave this can be a good thing or a bad thing. For me, this was a bad thing.
My problem came while I was writing unit tests to check the value of an updated row in one of my tables. After I updated the row, I queried the table (using linq) expecting to receive the updated values. I did not get the updated values and my tests failed. My test looked something like this in pseudo-code:
1) Create a new People record by using email address test@test.com
2) Get a People object by using the email address test@test.com
3) Validate the people object is not null (Assert.IsNotNull)
4) Update the Password column value to "1234" using a stored procedure
5) Get a new People object using the email address test@test.com
6) Check the first people object password property to validate that it is different than the second people object password property. <-- This failed
The issue was LINQ was caching the first object after the first call to get the people object (Step 2 above) and then giving me the same object when I wanted to retrieve the new people object (Step 5 above).
The first thing I did was check the "Auto-Sync" property for the columns on the People entity in my LINQ TO SQL data model. It was set to "Always" which led me to believe this would always be refreshed. After confirming this was the case that got me to thinking about why this wasn't working. The conclusion I came up with is I was not updating the table using the DataContext.SubmitChanges method rather I was using a stored procedure.
I found a post online stating to use DataContext.Refresh. I tried this but quickly found out that by using the Refresh method LINQ was actually querying the database twice. That is obviously something I wanted to avoid.
After doing a little more research I found out that the issue was "object tracking". Apparently object tracking is the caching mechanism in LINQ TO SQL. Long story short, whenever you create the DataContext, set the ObjectTrackingEnabled to false and this caching issue goes away. The following is my function to get the datacontext for my linqtosql layer.
Private mDb As MyDataContext
Public Function GetMyDataContext() As MyDataContext
If mDb Is Nothing Then
mDb = New MyDataContext
mDb.ObjectTrackingEnabled = False
End If
Return mDb
End Function
Make sure you only set the ObjectTrackingEnabled property before querying any entities. Otherwise an error will be thrown.
Technorati Tags:
LINQ,
LINQ TO SQL,
.NET 3.5
posted @ Monday, January 14, 2008 5:46 PM