Working locally

The subject of this chapter is queries, but in a real application, you don’t just run queries for their own sake; you want to do something with the results. That’s not always as straightforward as it might appear, but the DbSet.Local property makes it simpler:

You can bind directly to the context (once you’ve loaded the data), but that presents some problems if you want to run additional queries, for example to allow your users to find a specific entity. The problem is that the EntitySet and DbSet are actually queries. Think about what happens if you execute code like this:


Image

Recipe theRecipe = (from r in context.Recipes
         where r.Name = "Denver Omelet").Single()


You might expect that to return the Denver omelet you’ve been working with in memory, but it won’t. Instead, it will make a trip to the database and tell you what the database has to say about Denver omelets. It won’t include any changes you’ve made, and it won’t find a Denver omelet that has been added but not yet saved. It will include entities that have been marked for deletion, if those haven’t been saved, and that’s probably not what you want either.

The DbSet<T>.Local property does what you might have expected querying the entity set to do. Queries against Local return their results based on the entities in memory—no database trips required. They include any changes or additions that haven’t yet been saved, and they don’t include entities that have been marked for deletion. (They also don’t include database rows that have been added but not loaded into memory, but hey, you can’t have everything.)


Image

Recipe theRecipe = (from r in context.Recipes.Local
         where r.Name = "Denver Omelet").Single();


It’s possible to get the same results when you’re working with an ObjectContext instead of DbContext, but not in a single step, and the technique isn’t pretty. We’ll talk about the ObjectStateManager and ObjectEntry classes in detail in the next chapter, but here’s a preview of coming attractions:

The ObjectStateManager, which is exposed as a property of the ObjectContext, manages a set of ObjectEntry instances—one for each entity the context is tracking. The ObjectStateManager.GetObjectStateEntries() method will return an IEnumerable<ObjectEntry> for the specified states. The ObjectEntry class has an Entity property that makes it possible to filter the results and get access to the actual entity.

So, the equivalent to Recipes.Local using an ObjectContext would be:


Image

var localRecipes =  context.ObjectStateManager
  .GetObjectStateEntries(EntityState.Unchanged
       || EntityState.Modified
       || EntityState.Added)
  .Where(e => e.Entity is Recipe)
  .Select(e => e.Entity as Recipe);


As I said, we’ll look at the ObjectStateManager and ObjectEntry classes in detail in the next chapter. They’re actually quite useful. But when it comes to retrieving in-memory entries, I know which API I’d rather use...


Image On Your Own

The Local property is easy to use, and the ObjectContext version is ugly, but do-able (it’s what the DbSet uses under the covers, after all). But it presupposes that you only want to query the entities that the context is tracking. Think through some possible scenarios: how often would you actually want to do this?


..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset