Archive

Archive for the ‘Entity Framework’ Category

Re-attaching objects – My Foray into Linq to Sql and the Entity Framework (part 2 of 2)

March 3, 2009 2 comments

This is the second part of a two part series on Linq to Sql and the Entity Framework. In the first part we talked about the two different frameworks. Specifically we talked about detached objects. This part of the series will discuss the options to re-attach objects. We will be discussing this in terms of Linq to Sql. However, the “ideas” will work for the Entity Framework also.

How do I Re-attach my objects?

During my research I found 3 different techniques for re-attaching objects. Each of these techniques has pros and cons, so I will attempt to explain each one. I will be explaining these techniques in terms of Linq to Sql. However, the architectural decisions are the same with Linq to Sql or the Entity Framework.

Technique 1: Re-Query

The re-query technique is basically re-querying the database in your save routine. The reason to use this is to get the “original” values back before you save. However, there are some serious downsides to this technique.

Here is an example of this technique in action. Let’s say we have already done our retrieve and then hit the save button on our asp.net application. A postback ran and we filled in an “Employee” object. Now we have to attach that employee object to our context to save. However, if we just attach it, then the framework will always thing the object is “New”. So, we will re-query to get the original values so the framework knows we are doing an update.

//Instantiate a context to do our save

MyDataContext saveContext = new MyDataContext();

 

//Run a query to get the “original” objects

MyDataContext origContext = new MyDataContext();

Employee origEmp = origContext.Employees.Single(e => e.EmployeeID == 1);

 

//Attach the new employee object to the save context and pass in the original context

//so it can do concurrency checking

saveContext.Employees.Attach(newEmp, origEmp);

saveContext.SubmitChanges();

 

The above technique will seem like it works. However it has two issues:

1.       Performance – there is no need to run that extra retrieve when saving

2.       Concurrency – this is not really checking concurrency, it is doing a fake check

Let me explain a little more why this is doing a fake check. Let’s take an example of two users in a system. This system has a status field and the users really need to know the current status when they are changing data because another user might have already made the changes that they wanted to make for this particular status.

1.       User 1 retrieves the data

2.       User 2 retrieves the data

3.       User 2 updates the data

4.       User 1 updates the data

That is a concurrency issue on step 4. When User 1 updates the data, they should know that someone else slipped in an updated the data before them and they never saw that updated data. Well, in the above approach where you query the data in the save logic, just to get the original values, you are not really solving the underlying problem. Because User 1 just retrieved User 2’s data when they were saving and never saw the changed data. Concurrency checks will all pass and User 1 will never know there was an issue.

So, I don’t ever recommend this technique if concurrency is something you need in your system.

 

Technique 2: Session

Using session to store your objects across PostBacks is a valid technique to keep original data around. The basic steps are to retrieve the data in load, set that data to session, run the save PostBack, get the data out of session and reset the fields with the data from your user controls.

This sounds easy, but there are many considerations when using this technique.

Consideration 1

Session can hurt performance of a server and eat up resources. You have to be very careful when using Session on an asp.net application. If your objects are too large, then you don’t want to store them in session. Also, if you have many users accessing the system at the same time, session can become an issue. So, weigh in the normal architectural decisions of using Session when validating this approach.

Consideration 2

You have now disconnected the original object and want to re-attach it to the context. Don’t you lose all “state” information (i.e.: new, modified, deleted, etc…)? Well, yes, you do. But, this is where that Code Plex project I mentioned earlier comes in to play http://www.codeplex.com/LINQ2SQLEB. This keeps the state and original values in the base class for the objects, instead of just keeping them in the context. And, it reattaches the objects to a new context and sets all this information. Thus, I can serialize my objects, reattach them to my data context and still have my original values and state around for optimistic concurrency checks.

Consideration 3

Linq to Sql objects are not marked as Serializable. Thus, they can’t just be set into session easily. However, the Entity Framework objects are marked that way, so this is only an issue with Linq to Sql.  Luckily, there is a trick to this. Linq to Sql does support DataContracts. Thus, you can use the DataContactSerializer to store Linq to Sql objects in session http://www.squaredroot.com/post/2008/01/30/Storing-LINQ-Objects-in-SQL-Based-Session-State.aspx

 

This technique was the approach I picked for my last project. We had other architectural decisions in which we were storing objects in session anyways, so it seemed like a perfect fit. And, because of this technique, and the base class I found (LINQ2SQLEB) is the only reason I picked Linq to Sql over the Entity Framework. If there was something available like this for the Entity Framework, I would use it in a second. Hum, maybe I will create something like that.

Note on Technique 2

Be careful with this technique and the concurrency checking mechanism of Linq to Sql. When you re-attach your object, to do an update, here is what the update statement will look like:

@originalValue1 = 02/11/2009 12:33:31 PM

@originalValue2=”testing”

@newValue1 = 02/13/2009 12:33:31 PM

@newValue2=”test”

UPDATE [MyTable]

SET [lastUpdatedTime] = @newValue1, [field1] = @newValue2

WHERE ([lastUpdatedTime] = @originalValue) AND ([field1] = @originalValue2)

 

This is fine and the update statement will do optimistic concurrency perfectly. However, there is a performance consideration here. The update statement builds a check on every field in the “Where” clause. This can make a bloated sql statement when you are updating lots of fields. If you want to clean up these sql statements, here is my suggestion. Add a field to your table in the database that always changes, I recommend a timestamp field in sql server. Then, go to your Linq to Sql designer and turn the concurrency check from “Always” to “Never” on all your fields except this timestamp field. This way, the timestamp field is the only field that will be checked in the “Where” clause. You will still have the same optimistic concurrency and a much quicker update statement.

capture

 

Technique 3 – Manually attaching with timestamp

The last technique I want to explain is how to manually attach an object with a timestamp field. In this technique we retrieve our data in the load, set a timestamp field to ViewState, run the save on PostBack and use that timestamp field to set the original values.

The technique is actually quite simple when seen in code. Below I am showing the save code. Assume we have already loaded the data and set the timestamp field to a ViewState attribute marked _timestamp.

 //Instantiate a context to do our save

MyDataContext saveContext = new MyDataContext();

 

//Create a new employee object to fill in

Employee emp = new Employee();

 

//reset the timestamp viewstate field “before” I attach to set the original value

emp.timeStamp = _timeStamp;

 

//Attach the object after setting the timestamp.

//This creates an object in state “New”

saveContext.Employees.Attach(emp);

 

//set the values from our user controls

Emp.FirstName = txtFirstName.Text;

Emp.MiddleName = txtMiddleName.Text;

Emp.LastName = txtLastName.Text;

 

saveContext.SubmitChanges();

 

Keys to making this work:

1.       Set the original value, from ViewState, before you attach the object.

2.       Set the new values, from your user controls, after you attach the object.

3.       Turn the “Update Check” to “Never” on all the fields except for the timestamp field in the Linq to Sql designer.

capture

 

How this works:

Basically, you create a new Employee object. At this point, all the fields (timestamp, FirstName, MiddleName, LastName) are set to null and the state is “New”. Then you set the timestamp field from ViewState. This sets that value to the “original” value we got when we loaded. The state is still “New” at this point. Then we attach to the context. Once the object is attached to the context, any change we make turns the state from “New” to “Modified”. So, when we set the FirstName, MiddleName and LastName we are telling the context that we modified data. This will build an update statement like this:

 

@originalTimeStamp = “3289t5u23940uewu903285”;

@originalFirstName=null;

@originalMiddleName=null;

@originalLastName=null;

@newTimeStamp = “3289t5u23940uewu903285”;

@newFirstName=”Greg”

@newMiddleName=”Brian”;

@newLastName=”Galipeau”;

UPDATE [MyTable]

SET [TimeStamp] = @newTimeStamp, [fName] = @newFirstName, [lname] = @newLastName, [mName] = @newMiddleName

WHERE ([TimeStamp] = @originalTimeStamp)

 

The issue with this approach is that it will always think that it needs to update the fields in the database. Because the original value for the First, Middle and Last names always are null, it always thinks we changed them. This is not necessarily a bad thing. You will have to decide that for your architecture. If it is a bad thing, and you really want to use this approach, then you have to set those values in ViewState when you load also. That way you can set the original values, before you attach, and the tool can do a real check against the value to see if you actually made any changes. This process of setting everything into ViewState could become quite cumbersome on larger forms.

The following example assumes I stored the original first, middle and last names in ViewState on the page load.

//Instantiate a context to do our save

MyDataContext saveContext = new MyDataContext();

 

//Create a new employee object to fill in

Employee emp = new Employee();

 

//reset the viewstate fields “before” I attach to set the original value

emp.timeStamp = _timeStamp;

emp. FirstName = _firstName;

emp. MiddleName = _middleName;

emp. LastName = _lastStamp;

 

 

//Attach the object after setting the timestamp.

//This creates an object in state “New”

saveContext.Employees.Attach(emp);

 

//set the values from our user controls

Emp.FirstName = txtFirstName.Text;

Emp.MiddleName = txtMiddleName.Text;

Emp.LastName = txtLastName.Text;

 

saveContext.SubmitChanges();

 

  

Conclusion

So far these 3 techniques are the best ones I have found for re-attaching disconnected objects using Linq to Sql or the Entity Framework. If you have any other suggestions please leave a comment. And, let’s just “hope” Microsoft one day realizes this scenario and gives us better options, such as the option to have a mini-datacontext that we can store in Session. That would be nice!

My Foray into Linq to Sql and the Entity Framework (Part 1 of 2)

February 28, 2009 2 comments

Recently I had a project in which I knew that I wanted to use one of the new O/RM tools from Microsoft. If you don’t know what an O/RM tool does, then let me give my brief explanation. An O/RM tool creates mappings from the database to an object models. This really cuts down on manual mappings and manual creation of objects and is a great option for Rapid Application Development.

Why are there two tools?

So, the most obvious question is – why are there two tools for O/RM in the Microsoft stack? Well, I am not really sure, but I know the timeline a little – so you can draw your own conclusions.

Linq to Sql came out first and Linq to Sql was never even supposed to exist. Well, at least that is what Matt Warren’s blog says: http://blogs.msdn.com/mattwar/archive/2007/05/31/the-origin-of-linq-to-sql.aspx.  So, what happens at your company when a developer builds something and it gets released even though it wasn’t spear headed by the company – politics begin? I am not saying that happened here, but soon after Linq to Sql comes out we have a new O/RM tool from Microsoft, the Entity Framework. This new tool does almost everything Linq to Sql does, and it does it in similar ways. But, it was created separately and it scales a little more. Even though some people think that some of the smaller nuisances in Linq to Sql are actually better than the Entity Framework, but that debate is not one I will get into during this blog.

This new O/RM tool, the Entity Framework, has the ability to hook into more database types. It also has some more advanced mapping configurations. It decouples the database structure from the logical data model better than Linq to Sql. And, it is easier to use with stored procedures. However, it is not as “lightweight” as Linq to Sql and is suppose to work with all databases, thus it doesn’t take advantage of some of the unique features of particular databases. But, hopefully some better adapters will come out soon for particular databases that will increase performance.

I heard Microsoft was killing off Linq to Sql?

Well, I am not 100% sure yet on this statement. From what I hear Microsoft will continue to “support” Linq to Sql, however we might not see any extra features added to it. I have seen statements that Microsoft will continue to invest in Linq to Sql based on customer feedback, but the Entity Framework is the recommended data access solution for .net 4.0. What this tells me is that when .net 4.0 comes out we will see enhancements to the Entity Framework and we will continue to see enhancements to the Entity Framework from there on out. But, at the same time the word “dead” might not be appropriate for Linq to Sql. While we might not see many improvements, Microsoft should continue to support this technology.

Please refer to this article by Jonathan Allen on InfoQ explaining these thoughts a little more: http://www.infoq.com/news/2008/11/DLINQ-Future

Also, here is the Microsoft blog that clarifies the future of Linq To Sql: http://blogs.msdn.com/adonet/archive/2008/10/31/clarifying-the-message-on-l2s-futures.aspx 

Choosing one or the other

Well, based on my previous statements you would think it is obvious to choose the Entity Framework. However, on my last project I actually still chose Linq to Sql. Why would I do that? It has to do with established patterns and tools, let me explain. I was building an asp.net application and I wanted to use a repository pattern.

The repository pattern allows me to set up Retrieve, Update, Insert, etc… statements in a repository class. This class takes care of using my object to attach to the data context in Linq to Sql and then runs the respective Linq to Sql data access operation. It is a great pattern and one I recommend for asp.net projects and multi-tiered projects in Linq to Sql.

Well, one big feature of the repository pattern is re-attaching disconnected objects. On this particular project we had a real short deadline and needed every advantage we could get. Plus, this project had a very well defined database that mapped perfectly to the object model. It was really setup for a lightweight O/RM tool. Luckily, I found a project on CodePlex specifically designed to re-attach disconnected objects in Linq to Sql – http://www.codeplex.com/LINQ2SQLEB. This project is basically a base class for Linq to Sql that has the ability to re-attach disconnected objects. I couldn’t find anything similar for the Entity Framework at this point (probably because it is newer). So, that is why I decided to go with Linq to Sql.

What do you mean when you keep mentioning Disconnected Objects?

Ok, I have mentioned Disconnected Objects a bunch in the last section. So, if you don’t understand what I mean by that, let me explain the architecture of both Linq to Sql and the Entity Framework a little. Both of these tools use a graphical interface that creates your objects. However, they actually create two things:

1.       Context

2.       Objects

So, the first thing to understand is what is a context versus an object? The easiest one to understand is the objects. These are the actual objects that represent the tables in your database. These are dynamically built by the frameworks, but they are basically classes with properties (just like we would do if we did the mapping manually ourselves). So, there is nothing too fancy about the actual objects that get created.

The fancy stuff in these frameworks is the Context. The Context is what you use to populate the objects. For example, you want to run a retrieve, you tell the Context to retrieve the data and it populates the objects. Or, you want to save, you tell the Context to save, and it saves the objects that were previously retrieved. The Context also remembers “state”. State is important because it remembers if the object is New, Modified, Deleted, etc… This becomes really important during save operations. The framework needs to know the state to know what kind of sql statement to run (Update, Insert, Delete). The Context also keeps the original values from the initial load and can use these initial values to do optimistic concurrency checks when saving. This architecture is great for WinForM or Silverlight applications, but can produce issues with Postback scenarios in asp.net (we will explain this later in the article).

So, hopefully I adequately explained what the Context does and what the Objects are for. But, I still haven’t explained Disconnected Objects. Disconnected Objects can happen in many ways, but I will explain in terms of asp.net. Let’s say you use the Context, to call the framework, to populate your objects. And, let’s say you are doing this in the OnLoad of your asp.net page. Now let’s say the normal asp.net processing takes place and when you finish the user hits the Save button. The Save button does a PostBack at this point. Well, there is your issue. As soon as you do the PostBack you have lost the reference to your Context and your objects.

Ok, I have lost my references, how do I get them back. Well, you could just instantiate new objects and fill them in. However, that is all you will have, new objects. This is now a Disconnected Object scenario. Your objects have been disconnected from your Context.

In the next part of this series we will discuss the different options for reattaching those disconnected objects.