O'Reilly logo

Programming Entity Framework: DbContext by Rowan Miller, Julia Lerman

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

Chapter 4. Working with Disconnected Entities Including N-Tier Applications

In the previous chapter you learned how to add new entities and change or delete existing entities. All the examples we looked at involved making changes one at a time to entities that are tracked by the context. Each of the changes affected a single entity or relationship. You saw that you can perform multiple of these single entity operations and then call SaveChanges to push all the changes to the database in a single transaction. In this chapter we will look at making changes to entities that are not being tracked by a context. Entities that are not being tracked by a context are known as disconnected entities.

For most single-tier applications, where the user interface and database access layers run in the same application process, you will probably just be performing operations on entities that are being tracked by a context. Operations on disconnected entities are much more common in N-Tier applications. N-Tier applications involve fetching some data on a server and returning it, over the network, to a client machine. The client application then manipulates this data before returning it to the server to be persisted.

The N-Tier pattern makes data access more complex because there is no longer a context tracking changes that are made to each entity. The data is fetched using one context, and returned to the client where there is no context to track changes. The data is then sent back to the server and must be persisted back to the database using a new instance of the context.

Note

While the majority of content in this chapter is aimed at developers writing N-Tier applications, it’s useful information for anyone working with Entity Framework and will give you a deeper understanding of how Entity Framework behaves.

When it comes time to persist the data on the server, you are typically working with a graph of entities. A graph of entities is simply a number of entities that reference each other. We’ve already worked with graphs of entities that are attached to the context. In the last chapter we looked at adding a relationship using a navigation property, which is enough to create a graph, because one entity now references another. In N-Tier scenarios this graph of entities is usually disconnected from the context, though, meaning the context isn’t yet tracking any of the entities in the graph.

When it comes time to start performing operations on this disconnected graph, there are some additional behaviors in Entity Framework that you need to be aware of. The entity that you perform the operation on is known as the root of the graph. Performing an operation on the root of disconnected graph can have side effects on the rest of the graph, too.

A Simple Operation on a Disconnected Graph

Before we delve into the complexities of N-Tier scenarios, let’s take a quick look at an example of the side effects of performing an operation on the root of a disconnected graph. In the previous chapter we saw that DbSet.Add can be used to register a new entity to be inserted when SaveChanges is called.

Note

You’ll see the term register used throughout this chapter. When an entity is registered with the context it means that the context becomes aware of the entity and starts tracking it.

So far the entities we’ve passed to the Add method have been standalone instances with no references to other entities. Now let’s see what happens when we pass the root of a newly created graph of entities that isn’t yet tracked by the context. Add the AddSimpleGraph method that is shown in Example 4-1.

Example 4-1. Method to add a graph of entities

private static void AddSimpleGraph()
{
  var essex = new Destination
  {
    Name = "Essex, Vermont",
    Lodgings = new List<Lodging>
    {
      new Lodging { Name = "Big Essex Hotel" },
      new Lodging { Name = "Essex Junction B&B" },
    }
  };

  using (var context = new BreakAwayContext())
  {
    context.Destinations.Add(essex);

    Console.WriteLine(
      "Essex Destination: {0}",
      context.Entry(essex).State);

    foreach (var lodging in essex.Lodgings)
    {
      Console.WriteLine(
        "{0}: {1}",
        lodging.Name,
        context.Entry(lodging).State);
    }

    context.SaveChanges();
  }
}

The code constructs a new Destination instance, which also references two new Lodging instances in its Lodgings property. Then the new Destination is added to a context using the Add method. Once the Destination is added, the code uses the DbContext.Entry method to get access to the change tracking information that Entity Framework has about the new Destination. From this change tracking information the State property is used to write out the current state of the entity. This process is then repeated for each of the newly created Lodgings that are referenced from the new Destination. If you modify the Main method to call AddSimpleGraph and run the application you will see the following output:

Essex Destination: Added
Big Essex Hotel: Added
Essex Junction B&B: Added

It’s no surprise that Entity Framework has the new Destination registered as an Added entity because we used the Add method to add it to the context. What may be a little less obvious is that Entity Framework looked in the navigation properties of the Destination instance and saw that it referenced two Lodging instances that the context wasn’t already tracking. Entity Framework also registers these entities as Added and will insert them into the database when SaveChanges is called. The process of finding related entities is recursive, so if one of the new Lodging instances referenced a new Person instance, the Person would also get added to the context. Figure 4-1 attempts to visualize how calling Add on a disconnected Destination will also add other disconnected entities that are reachable from the Destination.

Adding a disconnected graph of entities

Figure 4-1. Adding a disconnected graph of entities

If a reference is found to an entity that is already tracked by the context, the entity that is already tracked is left in its current state. For example, if one of our new Lodging instances referenced an existing Person that had been queried for using the context, the existing Person would not be marked as Added. The existing Person would remain in the Unchanged state and the Lodging would be inserted with its foreign key pointing to the existing Person. Figure 4-2 attempts to visualize how adding a disconnected Destination will also add other disconnected entities, but if an entity that is being tracked by the context is found, it is left in its current state.

Adding a disconnected graph that references a tracked entity

Figure 4-2. Adding a disconnected graph that references a tracked entity

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required