Working with Entities in Code

Studio for Entity Framework (SEF) is non-intrusive in the sense that you can do whatever you want with entities in code using the regular Entity Framework (or RIA) methods and properties and that will work well with SEF. You can add, delete and modify entities using the regular methods (no special SEF object model is needed for that), and SEF collections will automatically reflect changes that you make to the entities. For example, to add a new entity, you don't need to use some special SEF method; therefore, none exists. Just add a new entity as you always do in EF (or RIA) and it will automatically appear in corresponding SEF collections. If an SEF collection has a Where condition, it will appear there only if it satisfies the condition. Same with deleting and modifying entities: do it the regular EF (or RIA) way, and SEF reflects the changes automatically, so they are automatically reflected in bound controls.

However, there is one important restriction that must be strictly observed. It does not limit what you can do; it only requires you in some (relatively rare) cases to add a method call to your code notifying SEF of what you are doing:

 

  CAUTION

 

Never fetch entities from the server by directly querying the context without notifying SEF.

All entities must be either fetched by one of the SEF's GetItems methods, or, if you want to fetch them by querying an object context directly, you must call the ClientScope.AddRef method to notify SEF that you fetched entities from the server.

If you use the C1DataSource control or ClientViewSource, you fetch entities either implicitly if AutoLoad = true, or explicitly when you call the ClientViewSource.Load method. In both cases it is done through SEF, so SEF is aware of the newly fetched entities. When you need to fetch entities in code without using ClientViewSource, the standard way to do it is by using one of the SEF's GetItems methods (EntityClientScope.GetItems, RiaClientScope.GetItems). Here too, SEF is aware of the fetched entities. However, occasionally you may need to retrieve entities by issuing a query directly to the server without involving SEF. For example, in Entity Framework you can take an ObjectContext that is used by SEF and create queries:

ObjectContext context = scope.ClientCache.ObjectContext;

// or

ObjectQuery query = ((NORTHWNDEntities)context).Customers;

// or

query = context.CreateObjectSet<Customer>();

// or

query = context.CreateQuery<Customer>("...");

In RIA Services such code can look like this:

DomainContext context = scope.ClientCache.DomainContext;

var query = ((DomainService1)context).Customers;

// or

var entities = context.Load(

((DomainService1)context).GetCustomersQuery()).Entities;

Having a query, you can get entities directly from the server by enumerating the query result

foreach (Customer c in query) /* do something */

or by binding a control to it:

dataGrid.ItemsSource = query;

If you do this without calling ClientScope.AddRef, you can get entities from the server without SEF knowing about it. Those entities will be in the same cache with other entities, indistinguishable from them, so SEF will manage them as other entities, including possibly releasing them, evicting them from the cache when it does not need them. That will make the entities inaccessible, but your program may still need them! So, very bad things can happen if you fetch entities to a SEF-governed context without using SEF and without notifying it that entities are fetched. Fortunately, adding that notification is easy, just call ClientScope.AddRef for all fetched entities like this:

foreach (Customer c in query)

{

scope.AddRef(c);

// do something

}

It will tell SEF that the entities should not be released as long as the scope is alive.


Send us comments about this topic.
Copyright © GrapeCity, inc. All rights reserved.