WCF RIA Services contains a special domain service for entity framework which will automatically be used if you use the Domain Service template in Visual Studio.
This winter I tried the template with a few projects. One of them had EntityObjects and the other had POCO entities.
The EntityObjects worked great, but the POCO entities didn’t work at all.
The bulk of the problems were based on the fact that the EntityDomainService used methods from the first version of Entity Framework that relied on EntityObject being passed in.
I showed this to some of the RIA Services team and how using ObjectSet methods and other .NET 4 methods would easily fix this so that the EntityDomainServive would work with EntityObjects and POCO entities which do not inherit from EntityObject.
The new RIA Services bits released at MIX reflected most of these changes to the EntityDomainService template. Here’s a domain service generated from a POCO entity.
[EnableClientAccess()]
public class DomainService1 : LinqToEntitiesDomainService<AdventureWorksSuperLTEntities>
{
public IQueryable<Customer> GetCustomers()
{
return this.ObjectContext.Customers;
}
public void InsertCustomer(Customer customer)
{
if ((customer.EntityState != EntityState.Detached))
{
this.ObjectContext.ObjectStateManager.ChangeObjectState(customer, EntityState.Added);
}
else
{
this.ObjectContext.Customers.AddObject(customer);
}
}
public void UpdateCustomer(Customer currentCustomer)
{
this.ObjectContext.Customers.AttachAsModified(currentCustomer, this.ChangeSet.GetOriginal(currentCustomer));
}
public void DeleteCustomer(Customer customer)
{
if ((customer.EntityState == EntityState.Detached))
{
this.ObjectContext.Customers.Attach(customer);
}
this.ObjectContext.Customers.DeleteObject(customer);
}
}
But there is still one more tweak you need to make.
Notice that the EntityState property is used in the Insert and Delete methods. EntityState is exposed by EntityObject so classes that inherit from EntityObject will have an EntityState property. POCO classes, however don’t have an EntityState property. Even if they did, these methods rely on the EntityState value that the ObjectContext supplies, which is what EntityObject.EntityState provides.
So this template still won’t work with POCOs.
Here’s how you can fix that.
Introduce a method into the class that knows how to read the EntityState from the context.
private EntityState GetEntityState(object entity)
{
System.Data.Objects.ObjectStateEntry ose;
if (this.ObjectContext.ObjectStateManager.TryGetObjectStateEntry(entity, out ose))
return ose.State;
else
return EntityState.Detached;
}
Then replace code which needs EntityObject.EntityState with a call to this method.
In the above example, it is two calls to customer.EntityState which need to be replaced.
OLD: if ((customer.EntityState == EntityState.Detached))
NEW: if ((GetEntityState(customer) != EntityState.Detached))