Click here to Skip to main content
15,887,135 members
Articles / Entity Framework

Getting inspiriation to solve problems

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
17 Sep 2009CPOL6 min read 10.7K   8  
This time I would like to share an experience with you that I had trying to get inspiration to solve issues more effectively.


This time I would like to share an experience with you that I had trying to get inspiration to solve issues more effectively. I'll line out the issue, which involves saving to the database through Entity Framework and how I got inspired. Of course, we'll also look into the solution I found after getting inspired.

Inspiration

A lot of times when I tell non-developers that building good software is actually a creative activity, more than it is a technical one, they look at me like I'm telling them I'm the Queen of England. However I'm not the only developer who gets stuck every now and then, not so much because I face such a hard to solve problem, but simply because I have a lack of inspiration.
The general consensus is that it helps to put your mind on other things, however in this case I felt I needed to regrasp the spirit of doing cool code. I surfed around a bit and ended up on Channel 9. I browsed through the latest videos and found a video about Windows 7 and how the kernel no longer uses dispatcher locks. You can watch it here.

Now, this is obviously not on topic for anything I do, as I'm working on a Line Of Business application. Also a lot of what was being told was completely new for me, because I never had such an in depth look at the Windows kernel, however the way Arun Kishan explores the issues with the dispatcher lock and with possible solutions to the problem, were very inspiring to me.

The Issue

I started to describe my issue to myself. We have been building a framework that uses a generic communication model using WCF to pass data between a webservice and our Silverlight client. In this framework, we have a single operation called UpdateItem which is responsible for saving any changes we make to the data (except for delete). So if I create a new business object, I pass it to UpdateItem and it persists it to the database. If I update a business object, again UpdateItem is called and it persists those changes to the database.

So far so good. However, I was building a popup in which a user is allowed to add items to a combobox, so it can then use these. I figured I would just create the business object without an ID, which indicates to the UpdateItem operation that this is a new object and it would then persist it in the database. It turns out it didn't. Here is why.

Two Types of Adding Data

In Entity Framework, you can add objects to generic ObjectQuery instances which are contained in the ObjectContext. Some digging showed we didn't use this, because in our application we have two different kinds of adding data.

The first type we implemented was adding data through so called 'parent' data. For example you can have a Person object, which can have children. Now if I add a Child, in the framework we've built, it knows about that and sets the Child.Parent property to the right Person object and the Entity Framework detects this as an insert. We never call an Add on the ObjectContext and that's fine, because we added it through some other object.

However in the situation I described earlier, the newly added object doesn't have any 'parent' data. It is just a sole record in some list somewhere, that may or may not get referenced by other objects. To be able to insert this, I would need a second type of insert that would directly call an Add near or on the ObjectContext somehow. More importantly, I would need some way to detect if the object actually did or did not have 'parent' data. To figure this out, I dove deeper into the framework.

The Internals of UpdateItem

If we have a look at our UpdateItem operation, this is basically what it does:

  • Deserializes the incoming data
  • Instantiates a new instance of the targeted business object
  • Loads the original data into the business object (if available)
  • Calls Save with the incoming data to persist it
  • Serializes the business object and sends the latest state back

All the magic happens in the Save, so let's have a closer look. The original Save consisted only of three parts. It would start with pre-save preparations, which are specific to an object. Then it would make sure that all the changes needed would be in an EntityObject and then it would call Save on the ObjectContext. This works fine for the first type of save, where we had the 'parent' data, but not if there is no 'parent' data.

Choosing a Solution

I figured I had several options to insert code that would fix the problem. The first option was to actually have this done in the pre-save preparations. This would allow me to fix the problem quickly now, however there are going to be a lot of these types of objects, that get saved without 'parent' data, so I decided to try and find a more generic solution that didn't need type specific implementation.

The second option was to expand the method that makes sure all the changes to the model are in the EntityObject (called BuildModelData). This would solve the problem, however determining if the object doesn't have 'parent' data is a very complex thing and BuildModelData was already complex as it was. So if I had no other choice I might go for it, but for the moment the search went on.

The final option was to expand Save, so it would somehow check if the object had 'parent' data or not and if not add it somehow to the ObjectContext. It would have to do so after BuildModelData and before calling Save on the ObjectContext. It turned out this was a lot easier than I expected.
The ObjectContext has a property called ObjectStateManager. This object actually keeps track of any changes made to the ObjectContext in any way. It has a method called TryGetObjectStateEntry, which allows you to see if an EntityObject is actually part of the changes made so far. It also provides information about the changes involved, but all I needed to know was if it was part of the changes or not.

Adding the object was even easier. The ObjectContext has an AddObject method, which takes a name and an EntityObject, both which I had already available. Here is the code I ended up adding:

C#
ObjectStateEntry objectState;
bool hasObjectState = 
	context.ObjectStateManager.TryGetObjectStateEntry(entity, out objectState);
if (!hasObjectState)
{
context.AddObject(name, entity);
}

As you can see, there is not much to it, but the best solutions are simple. However, testing with this I found out that the DeleteItem operation, used for deleting objects, also calls save, but then the EntityObject in entity is actually null (as it was deleted), so the Save would fail (although the object was still deleted from the database as well). A simple check on entity == null fixed that problem and now I can handle both types adding data through our framework.

I hope you've found this post as inspiring as it was for me to experience and write it. Please leave me comments if there is anything you need or want to share.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) KnowledgePlaza
Netherlands Netherlands
Since early 2001 I've been working full time as a software developer and since 2004 I've been working mostly with Microsoft technology.
I started out as a product developer, but after a few years I switched to a project company where my roles ranged from developer up to consultant and from team lead and coach to manager.
Eventually I switched jobs and focused on the consultant part and then I got back to building a product once again. Now I work in a job where I get to do both.

Comments and Discussions

 
-- There are no messages in this forum --