I’ve been playing with using EF object in code-behind of aspx web pages.
The first issue to hit is postbacks.
Entity Objects are Binary Serializable so they can be stored in ViewState.
Like many other objects, you need to put your entities into viewstate (I’ll deal with session and application caching in another post). Happily entities can be binary serialized so that happens for free when you add an entity object to ViewState. So you can persist the entities, but you cannot persist the ObjectContext, which is where all of the state information for the objects lives. Frankly, the objectcontext is very expensive and you wouldn’t want that in viewstate anyway.
The outcome of this is that even if you store the objects in viewstate, and pull them back out to attach to a new ObjectContext when you need them again, you will lose any state for the objects.
One saving grace is that objects stored in viewstate get updated automagically during postback. In other words, if I create a cust object and store it in viewstate, then make a change to the cust object, then postback and pull the object back out of viewstate, it will have the newer property values. Viewstate is synced up to the object.
That means we can be sure to have a current version of the object (or list of objects) hanging around as we muck with the page.
Binary Serialization keeps the entire graph in tact
The next piece of the puzzle is that if you have an obect graph (i.e. order with order details or cust with orders with orderdetails) that all gets persisted during binary serialization. That’s a big difference from xml serialization. The big reason is that XML serialization doesn’t know what to do with the relationships, which are also first class objets. The relationships “contain” all of the related data. So binary serialization can handle this. When you get the object graph out of viewstate, it’s got everything in it that it had when it went in.
Updating related data in an object that is in viewstate
This doesn’t act the way you might expect so listen up.
Say I have a cust object that has orders in it. i have saved the cust object into viewstate. If I edit a property of cust, say FirstName, that’s easy:
Viewstate syncs up that change just before the postback.
But what if I want to change something in one of the orders.
You need to do this directly in the cust object, not be extracting the order and changing it.
Here’s what I mean.
My first instinct is to do this:
myOrdtoEdit=(From ord in custs.Orders where ord.OrderID=123 Select ord).First()
On postback, that new ShippedData is not there.
But if I make the change this way:
cust.Orders.Where(Function(o) o.OrderID = currOrderid).First.ShippedDate=”7/1/2007″
The change is synched up. Good to be aware of.
What about concurrency? What if I need to remember original values?
I think the real solution is going to be is to have original values cached in another layer. But for the sake of working out the concepts, let’s say you are doing everything in code behind. Here’s how I’m solving this problem.
When I first get the values, I want to store them in viewstate, too. But if I do that, and I want to take advantage of the synching viewstate (I think I remember seeing that there is a page directive to turn that off, but don’t hold me to it), then the original objects will get overwritten.
So what I have done was explicitly serialize the original objects and store the resulting memory stream into viewstate. When it’s time to do an update, I deserialize that stream and voila, I have a set of original objects that I can use to compare my current objects to.
One object or more? How do I persist multiple objects?
Note that I have wavered between talking about persisting a single object and multiple objects. If you are dealing with a query that returned a collection of objects, then you don’t persist the query. Instead, convert the query to a list with .ToList and you will end up with List<Customer> / List(Of Customer) and that’s what you can put into viewstate. This is also what you would serialize, the list of customer objects.
When do I work with the objects again?
I have done various tests using databinding (gridviews, textboxes) or just manually getting and setting text properties.
Once you post back, the datasource is gone on a bound control anyway. I just work with the text values that are in the control. When I want to update an object, then I will get the object(s) from viewstate and modify them. Other than that, the only time I need them again is when it’s time to do an update back to the data store.
Sign up for my newsletter so you don't miss my conference & Pluralsight course announcements!