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))
Sign up for my newsletter so you don't miss my conference & Pluralsight course announcements!
Thanks for the sample. Do you know whether or not POCO support is part of WCF RIA Services 1.0 RC 2?
Not sure I understand this but my problem is with the entity state so I am asking it here along with other places. When I insert a record through a dataform in (Silverlight 4 VS2010 with a license and the latest WCF from 4/15) the first time it works fine. Second time I get "An entity with the same identity already exists in this EntitySet" This is a problem with the seed from the dataform. The first time the new id = 0 it’s fine. The 2nd time the entity that’s there obviously still has a 0. How does one either change the existing entity or delete it after the add? The samples like HRApp all have the same problem.
@Charlie, everything described above is in RC2.
@Larry, I’m not sure why you would be getting this problem. If you are seeing it everywhere, there’s either a problem with RIA or perhaps someone will recommend a different way to write your code. I’m definitely interested either way, so if you find the answer (my guess is the RIA Services forums on Silverlight.NET will be your best bet), please do come back and fill me (and other blog readers) in! Thanks.