Showing posts with label Entity Framework. Show all posts
Showing posts with label Entity Framework. Show all posts

Thursday, December 9, 2010

Adventures while building a Silverlight Enterprise application part #39

In this post we look at an issue we had while implementing a specific form of data entry for our application. Basically there was an oversight in our reasoning about CRUD operations that needed fixing. It also shows the power of GUID’s.

The situation

We are currently in the final sprint towards delivering our first new product release to a group of customers. As one might expect, we are in the process of testing the functionality that was built so far and we ran into some issues. One issue we encountered was hidden deep down in the framework and hidden behind some other bug in the Silverlight UI.

To get a better understanding of the issue we found, it’s important to have some basic knowledge about how are framework works, especially in terms of creating and updating records. We decided early on that creating a record is basically the same as updating one. The only difference in our service call is that we provide an empty GUID instead of an existing GUID. The framework should then detect that there is a new record, create a GUID for it and insert it into the Entity Framework context and all works well (except for the incidental problem with insert).

Recently we added two modules to our UI, which consist of a data grid. The data grid is filled with a default set of rows from one table and once the user fills in certain values, records are created in another table. In order to make this work there is a view which is added to the entity framework to provide the correct rows. We then have some code in the service layer to make sure we don’t get double rows when there are records available in the second table.

The bug

A bug occurred when we tried to enter a value into a record that was not yet available in the second table, saved the modules data and then change that value. Now we ended up with two records in the second table instead of one. A short debugging session revealed the cause. Both update actions where send with an empty GUID, so both we’re interpreted as an insert.

The solution

Solving it was not as easy. In order to prevent these kind of bugs, we already return an updated (or new for that matter) business object from the service. However, for new records, there is no id known (it’s empty), so we have nothing to match to, meaning we can’t update the record in the data grid, which leads to our problem.

In order to fix it, we would want to create a new GUID in the Silverlight client, send it to the server and use it there as well, however then our service would not interpret this as an insert. What we can do is send this new GUID in the actual property of the business object which we want to update. This did require an update of the framework where, in case of an insert (the passed GUID is empty) we now check to see if the business object has a GUID as it’s key already available then we use that GUID instead of generating a new one.

So now, we can generate a GUID in the client, send it with the insert and know which object was updated as soon as it is received in the service call back. This allows us to match the rows in our data grid to the business object and update accordingly, meaning no more double records.

In the end, this his the code we created to make sure we get a GUID if one is available:

   1:              idPropertyName = string.Format("{0}{1}", idPropertyName, IdSuffix);


   2:              PropertyInfo idProperty = dataType.GetProperty(idPropertyName);


   3:              Guid id = Guid.NewGuid();


   4:              if (idProperty != null)


   5:              {


   6:                  if (changedData.PropertyDictionary.ContainsKey(idPropertyName))


   7:                  {


   8:                      PropertyObject idPropertyObject = (PropertyObject)changedData.PropertyDictionary[idPropertyName];


   9:                      Guid requestedId = (Guid)idPropertyObject.CurrentValue;


  10:                      if (!requestedId.Equals(Guid.Empty))


  11:                      {


  12:                          id = requestedId;


  13:                      }


  14:                  }


  15:                  idProperty.SetValue(data, id, null);


  16:              }


  17:              this.Id = id;


  18:              SetProperty(this.IdProperty, id);


Friday, October 15, 2010

Adventures while building a Silverlight Enterprise application part #37

In this post we are looking at Entity Framework and specifically at some performance quirks.

The story

Recently we were testing part of our new software. One thing we noticed is that, besides the fact that the first time we load data, things are slow because of services starting up and Entity Framework loading metadata, also the first time we save some data, it is also slow.

We decided that is was worth investigating why this was happening. The goal was to at least come up with an explanation and some more insight into when this was occurring.

Analysis

Some preliminary analysis I made:

  • This was not the same thing as starting up the service and Entity Framework loading metadata because of that. I knew that because I had just loaded data from the same service and model that I was now saving to.
  • It was caused by something in the service. I could tell because we have a busy indicator active whenever a service request is pending completion.
  • It was not caused by any specific code for one of our business objects as it didn’t matter which object I would save. It was always slow the first time.

As you may know, if you are following this series for some time, we have a bunch of complex generic code that’s involved when either loading or saving data. I decided my first task was to identify exactly what line or section of code was causing the delay the first time around. To accomplish this I placed some debug code which would log the exact time to the debug output. This way I could easily calculate where a delay would occur.

By following this strategy I quickly found out that the delay for the first save occurred when calling SaveChanges on our model. However, reflecting the code for the method did not reveal any obvious cause for this. I searched on the internet to find out if anyone had already cracked this problem, to find out that only a handful of people had seen the same issue, but non of them actually resolved it.

As I still did not pinpoint the exact cause, I decided to build a test application to demonstrate the problem and hopefully get a better understanding. As we are currently still using version 2.0 of Entity Framework and running in .NET framework 3.5, I used Visual Studio 2008 to build my test application on top of the AdventureWorks database. I needed it to do basically two things:

  1. Load a single object from the model to initialize the Entity Framework model
  2. Save a change to a single object from the model and time the operation

To make my tests more flexible I decided on a WPF UI that allows me to control the above steps and it presents me with the results instantly. Check out the screenshot below:

EFPerformanceTest

The times displayed are in milliseconds. Let me explain what you see here. On top are two rows of buttons, one for the full AdventureWorks model and one for a model with only the Customers table (both models do connect to the same database). Below that is a listbox with performance results for each save action. At the bottom there is a general log to see what is happening.

Basically what you see in the performance logs is this. The first save action is done after loading a customer from the complete model. It takes a whopping 177ms. The next save action, after loading the same record again, takes only 2ms! This reproduces the issue we’ve been having.

Now the next step is doing exactly the same thing with a model that contains only the Customers table, so there is a lot less metadata to be loaded. It should be noted that both models are placed in separate assemblies to make sure metadata of one model is not interfering with the other. The time differences are a lot smaller between the first save (28ms) and the second save (4ms). Note that as performance is reaching lower limits times can fluctuate because of other processes on the system, which can account for the 2ms increase between the large model and the small model.

Because of this we can now conclude that Entity Framework loads some metadata as the first save occurs. Unfortunately we can not do much about that, but at least we now have an explanation.

Taking the next step

But the research didn’t end there. One of my colleagues suggested testing this with .NET 4.0 and Entity Framework 4.0 to see if there would be an improvement there. So I converted the project to Visual Studio 2010 and recreated both models using Entity Framework 4.0. The times are like this:

  • Saving the first time on the complete model: 82ms
  • Saving the second time on the complete model: 7ms
  • Saving the first time on the single table model: 36ms
  • Saving the second time on the single table model: 3ms

So work has been done in Entity Framework 4.0 to improve performance while loading metadata. Please note that my measurements were made on a system that is not exactly high performance and thus the measurements are not very accurate, however the differences between EF 2.0 and EF 4.0 with the first save are still significant enough.

Downloads

You can download the source of both versions of my test application:

Please be aware that the first project is a Visual Studio 2008 project and the second one is a Visual Studio 2010 project. You can however upgrade the first project, without changing the results.

Conclusion

So, although we can’t improve the performance of the first save action on an entity framework model right away, at least we can now explain what happens and what is the actual impact. As this only happens when IIS recycles the Application Pool for our web service, the impact is minimal. Also we can soften the pain as soon as we migrate our service to Entity framework 4.0.

I hope you have learned as much as I have writing this post. If you have any questions, please leave a comment below and I’ll be happy to help you out.

Monday, July 26, 2010

Adventures while building a Silverlight Enterprise application part #34

In this post we’ll look into analyzing performance in a Silverlight Line Of Business application, including multiple service layers and we come across a common problem using ADO.NET Entity Framework including a not so obvious solution.

The story

At the moment we are working on getting out a deliverable to a group of customers as soon as possible. However, one of the issues that keeps coming up is performance. A general response by a lot of developers is to just scour the web for performance tips on different technologies used in the stack and apply as many of them as they possibly can. However I find it much more useful to analyze the problem first.

Getting some data

To get a better feel for the problem, I first needed to get some numbers. When starting out with a performance issue the first question to get answered is “where is most time being spend?” This usually leads to the point where most time is being wasted as well.

At first I started out with profiling our application with Visual Studio 2010, but this wasn’t very useful to us as it didn’t show us any data on communicating with the service. I do feel compelled to link to some useful information on profiling your Silverlight application as it isn’t available through the IDE just yet and it requires you to jump through some hoops to get it to actually show you any performance data on your code. You can find a decent post by Oren Nachman on this here.

I should mention that profiling our application revealed one small performance issue with creating dynamic objects, which we use to instantiate modules in our application based on authorization and application settings. However, looking at the big picture it is hardly relevant to us, while hard to remedy it in a good way for our application.

The next step for me was to actually get data on communication with our services. As we designed our application in a way that we abstracted our service connections in seperate generic classes and we use generic service calls to get to our data, the easiest way for me was to simply record the DateTime.Now.Ticks. To keep the impact of this as low as possible on any production scenarios, I decided to write this information to the VS debug window, through Debug.WriteLine. Also to make sure this can be turned off easily to allow for other verbose debugging information, I introduced a conditional compilation symbol called DEBUGGINGPERFORMANCE and wrapped all my recording code with it. The code for me looked something like this:

   1: #if DEBUGGINGPERFORMANCE



   2:             Debug.WriteLine("BusinessLayerConnection.GetDataAsync<{0}>({1}): {2}", typeof(T).Name, id, DateTime.Now.Ticks);



   3: #endif


Running the application with this debugging code gave me some interesting data pointing me towards a specific operation, which gets all the data for a particular module at once. Within that set of modules one stood out that was taking far longer then the other modules, so I decided to investigate that further. I decided to use Fiddler to make sure none of this is actually caused by bandwidth issues. The statistics clearly showed my that the problem was with the service taking up a lot of time before actually starting to send a response.

This led me to put similar code in the webservice. Note that Debug.WriteLine doesn’t support the format approach by default and you should wrap that in string.Format. To actually make for a better performance test, I decided to build a small test tool to just make the same service calls several times in a row. This makes sure we’re working with correct numbers instead of chasing some random external factor.

As I started testing like this, I found out there where a lot of messages in the debug output stating that ‘A first change exception of type ‘ had occurred. In this case a large part of these exceptions where related to another service we use, which couldn’t access one of our databases. This was obviously an easy fix and it did improve performance considerably.


Fixing a common Entity Framework problem

After getting one exception out of the way, I found there where some more exceptions being thrown. The exact message that was displayed was: A first chance exception of type 'System.NotSupportedException' occurred in mscorlib.dll. Performance data indicated that this took roughly 3 seconds for six exceptions in each request!

I found it weird to see an exception like this. A web search didn’t return anything useful, except that it could be related to Entity Framework somehow. A forum thread pointed to this bug report about dynamic assemblies, which in itself wasn’t very useful information either.

I also found people asking questions about this message all over the internet, but without any real solutions. I turned on the System.NotSupportedException in Visual Studio, attached it to the service for debugging and ran my test again. As expected it halted in the debugger on the point where the exception was thrown. As expected it halted in mscorlib.dll, in this case in the System.Reflection.Emit.AssemblyBuilder class in the method GetManifestResourceNames(). This does confirm that it is actually caused by the bug I mentioned earlier, however it doesn’t really help us with a solution yet. The question now is, “why is someone calling this method on a dynamic assembly?”.

Browsing up the call stack makes it very clear that this code is being called from the Entity Framework. In fact it is called from the System.Data.Objects.ObjectContext constructor, but why? Taking a closer look at the call stack there is some indication that it must have something to do with initializing the metadata needed for the Entity Framework. It also reveals that the exception occurred in the System.Data.EntityClient.EntityConnection class in a method called SplitPaths. Looking at the code in that method and the state it was in as the exception occurred actually showed me what caused the problem. In the SplitPaths method there is a string[] called results (what’s in a name, right?) which contained three strings: res://*/Model.csdl, res://*/Model.ssdl and res://*/Model.mdl.

Looks familiar? That’s because these url’s are found in the default connection string for Entity Framework and they should point to the three files that make up the Entity Framework metadata. For some more documentation on that look here.

What was actually happening here was that a dynamic assembly was asked for it’s resources as the Entity Framework code was looking for a metadata file in all the loaded resources, as indicated by it’s connection string. The dynamic assembly that was loaded in this case was the binary for the WCF web service that hosts our DAL. The fix was simple. Just point to the exact assembly by it’s full name in the connection string for each metadata file and it’s fixed. This is how the metadata entry in our connection string looks now (obviously with some name changes):


   1: metadata=res://OurApp.Data, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null/OurModel.csdlres://OurApp.Data, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null/OurModel.ssdlres://OurApp.Data, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null/OurModel.msl;


I hope you found this search for this fix as useful as I did and it helps you out. Please leave me a comment if you have any questions.

30-07-2010 EDIT: Added the metadata part of the connection string to make the solution more clear. Thanks to greg-joyal for pointing that out to me.

Thursday, January 7, 2010

Adventures while building a Silverlight Enterprise application part #31

Today we want to look at an example I ran into where taking the time to think of good names for everything in your code can save the day.

First I'd like to explain my long absence. The last months of 2009 where obviously very busy for us, but besides that I've been moving to another house (sort of) and I've had a week off to finally have a bit of a rest. But on to more important things.

The story
For our new application I was working on some authorization logic in the service layer. We have a class that represents a user. I was implementing a method called IsUserAuthorized. When writing the virtual version of this in the base class, so all other business objects would be able to implement this behavior, I was thinking "I need to have the Guid identifying the user that should be authorized" and I named that parameter userId. Makes sense, right?

The problem
As I was implementing this method in the User class I simply used IntelliSense to generate the method stub for me and I started writing code. This is part of what I came up with at first:

var authorisations = from item in context.UserGroupAuthorisation
where context.UserGroupAuthorisation.Any(
i => i.Group.GroupId == item.Group.GroupId && i.Users.UserId == userId)
&& item.Users.UserId == this.UserId
select item;

It might seem a bit complex, but let me explain. What I'm doing here is, Because a user is a member of a group that user can also see other users in that group. So the determine if a user can see the user at hand I need to know what groups the user is a member of and see if any of these groups overlap with the groups of the user at hand. Basically, if the above query returns anything the user is allowed to request this user.

The solution
Now, from both the code and the explanation, you can see that it gets confusing, because we have two users in this story, who fill in different roles in this story. I was reading back my code to determine if I had done this the right way and I couldn't really grasp it. A simple tweak made a world of difference. Look at the revised code:

var authorisations = from item in context.UserGroupAuthorisation
where context.UserGroupAuthorisation.Any(
i => i.Group.GroupId == item.Group.GroupId && i.Users.UserId == requestingUserId)
&& item.Users.UserId == this.UserId
select item;

As you can see I renamed the parameter userId to requestingUserId. This has a more then expected impact on the readability of this code. Now you can see that our Lambda expression gets all the group authorizations for the requesting user and links them to the group authorizations in the query. Then all that is needed is to take only the authorizations for the user at hand, explicitly called by this.UserId so it's completely different from the parameter requestingUserId.

The conclusion
As you can see from the above example, having decent names, even for something small as a method parameter, can make all the difference when it comes to understanding code. May we all come up with better names!

Tuesday, August 18, 2009

Adventures while building a Silverlight Enterprise application part #19

This time I would like to share an experience with you that I had trying to get and getting inspiration to solve issues more effectively. I'll line out the issue, which involves saving to the database trough 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 then 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 trough the latest videos and found a video about Windows 7 and how the kernel no longer uses dispather locks. You can watch it here:


Get Microsoft Silverlight


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 dept 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 trouhg 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 build, 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 trough 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 he 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:
- Deserialize the incomming data
- Instantiate a new instance of the targeted business object
- Load the original data into the business object (if available)
- Call Save with the incomming data to persist it
- Serialize the business object and send 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.

Chosing 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 then 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, which I both had already available. Here is the code I ended up adding:
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 trough 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.

Wednesday, June 17, 2009

Adventures while building a Silverlight Enterprise application part #13

At times you run into decisions made at the early stages of design, that you regret, or at least find inconvenient. This happens to the best of us, especially when using new technologies. In our case we ran into the downside of using ADO.NET Entity Framework (EF) in our application and part #13 already looked like a good one to look at why this is the case.

Why EF doesn't always make sense
Because we are talking a big application here (several hundred forms and grids), and because we are using Silverlight 2 as our client, we decided to make a Business Layer Service, that takes care of our CRUD operations and make this generic. This means we now only have five operations instead of having over a thousand. This still makes us very happy as maintenance is low and you don't have to bother with a lot of code in this part of the system, however...

... in EF, whenever you do a save you need to supply all the connected entities or at least a reference it can use. For a small application with a very limited number of entities this is not a problem. Just code it up for each class and you're done. For our application however, we have a generic save and although we are able to write code for separate business objects (which translate into entities in our service), we'd rather not do this for something that should be the same for all our objects. I should state that this choice was a direct result of us using Silverlight 2 as our client. Writing several hundred save routines sounds like a job for an intern, which we don't have. :-)

We did end up building a generic save, but it did take some hassle to make it work in all scenarios. Especially combining both saving a new entity with saving an already existing one proved to be somewhat problematic.

If I then look further back in the process and see the effort that wend in to building the generic loading in several scenarios, getting a single item, getting a list of items based on some criteria, etc., I'm realy not sure if it was worth the effort with using EF. Why not just build your own?

The good
There is one reason however, and that's the model. The fact that you have in intermittend model that all your code is based on is something that may very well prove very valuable in the future. You could make changes to your datamodel and just change your mappings to go with it and presto, it still works.

If you're reading this and think to yourself: "Design your datamodel right and there is no need to do this", then you realy should get a few more years of experience in the new world. It is no longer acceptable to say that something can't be done, because the datamodel doesn't support it. Customers will not understand / don't care about this and just tell us to fix it and they are right (they eventually pay my salary :-) ).

Conclusion
So was it a bad choice? Should you or shouldn't you use EF in your larger applications? In our case I'd say it hasn't payed itself back yet, but it very well may still do that. I guess it still depends on your application and you should always have a good look at requirements like lifespan, scalability, performance, etc.. In general I think that EF can work for larger applications (as it does work for us), but you shouldn't be caught by what the demos try to make us believe. You can't build your data access services in a matter of minutes, especially if you need your service to work with Silverlight 2. It can still take months to do it with EF.

I hope this post is helpful to you when making your technology choices. Please leave any comments and/or questions below. I'm always happy to read and reply to them.

Wednesday, March 4, 2009

Adventures while building a Silverlight Enterprise application part #8

Well, it's been a while again. Sorry about that, but it's been really hectic around here.
At the moment we are digging into the back end of our application. You may remember from previous episodes that we use WCF services in our back end. One of the most important services in our project is our Business Layer Service. This service provides access on our database through ADO.NET Entity Framework.

So that's great. We can generate our data layer code, because we use EF, but how about the rest of our code? As we have a large amount of entities, one thing we didn't want to do was to provide service calls for each of them. It would be a lot of boring work, with high maintenance code as a result. So how would we make this generic?

Well, the WCF part of things isn't that hard. We defined a base class that provides us with a property bag. As we pass an instance of this class over the line, all that is send is a dictionary of keys and values. All our derived classes do, is access the property bag from the base class through properties. These derived classes, we generate from a meta data store.

Loading these objects from the EF is not as straight forward, but still not that much of an issue. We simply provide a string with the name of the object we want to the service, which we use to load the object through the EF method GetObjectByKey. We then reflect trough the properties of the resulting objects and fill the property bag of our generic class.

The real problems start when you want to provide a generic way to build lists of objects. We looked at many possible solutions, only to come up blank. Eventually it hit me, we needed a hybrid solution, between generic code and generated code. So I went looking for a solution using facilities provided in our base class to get to a list of specific EF entities and here is what I came up with:

public static IEnumerable<BusinessObjectBase> CreateList(Dictionary<string, object> criteria)
{
IEnumerable<BusinessObjectBase> result;
string queryText = GetQueryText("MyEntity", criteria);
using (CobraXeContext context = new CobraXeContext())
{
ObjectParameter[] parameters = GetParametersFromCriteria(criteria);
ObjectQuery<MyEntity> query = context.CreateQuery<MyEntity>(queryText.ToString(), parameters);
ObjectResult<MyEntity> objectResult = query.Distinct().Execute(MergeOption.PreserveChanges);
result = GetListFromObjectResult(objectResult);
}
return result;
}


On the service this looks easy, but actually getting to this point proved quite a challenge. Especially generating an EF query that worked, even if I needed to filter on properties from a different, but related entity was difficult. The documentation on joining in EF SQL is vague when it comes to it's exact syntax and it's also not completely intuitive as how to get to related information.
Eventually I came up with the following rule for building a query, which is implemented in the method above:

select value [entity] from [entity] join [jointable] on [entity].[joinproperty]=[jointable] where [predicates]


In my code I've assumed that the name of a joinproperty is always equal to the jointable name.

After building this and having my business classes regenerated, I started wondering about what code is to be generic, what is to be generated and what code is specific enough to be developed by hand, for a specific use. After thinking about this for several days, I came to the conclusion that there is no straight answer to this question. Maybe this decision is what has become part of our 'art', as I like to call it. Each situation is different and each program is different. I've worked on code for three months, only to have it run for two hours and never again. I've also worked on code for an hour and saw the same code being used years after.

Yep, it's been an interesting week. I hope you have learned as much as I have and I'm looking forward to read your comments.