Programming Guide > Working with Entities in Code |
DataSource for Entity Framework 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 C1DataSource. You can add, delete and modify entities using the regular methods (no special C1DataSource object model is needed for that), and C1DataSource 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 C1DataSource method; therefore, none exists. Just add a new entity as you always do in EF (or RIA) and it will automatically appear in corresponding C1DataSource collections. If an C1DataSource 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 C1DataSource 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 C1DataSource of what you are doing:
CAUTION
Never fetch entities from the server by directly querying the context without notifying DataSource.
All entities must be either fetched by one of the C1DataSource'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 C1DataSource 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 C1DataSource, so C1DataSource 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 C1DataSource's GetItems methods (EntityClientScope.GetItems|keyword=EntityClientScope.GetItems method, RiaClientScope.GetItems|keyword=RiaClientScope.GetItems method). Here too, C1DataSource is aware of the fetched entities. However, occasionally you may need to retrieve entities by issuing a query directly to the server without involving C1DataSource. For example, in Entity Framework you can take an ObjectContext that is used by C1DataSource 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 C1DataSource knowing about it. Those entities will be in the same cache with other entities, indistinguishable from them, so C1DataSource 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 C1DataSource-governed context without using C1DataSource 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 C1DataSource that the entities should not be released as long as the scope is alive.