Daily Archives: April 5, 2010

Rough Cuts version of Programming Entity Framework 2nd Edition: Ch 2-22

rc_lrgUpdate August 14, 2010: The Rough Cuts program is over and the book is now out in Digital Format. You can purchase the digital version directly from OReilly at http://oreilly.com/catalog/9780596807252. The print version should be shipping by August 20th. You can also purchase that through O’Reilly, Amazon or elsewhere.

In December, the first 5 chapters of the rough draft of Programming Entity Framework 2nd Edition (for EF4 & VS2010) were published to Safari Rough Cuts. There are now 20 chapters online there. There is no Chapter 1 yet and Chapter 4 is going to be split into 4 and 5. You’ll find that to make up for this split, there is no chapter 17 since 5 will become 6, 6 becomes 7, etc. Beginning with Chapter 18, the numbering is correct.

Just remember this is the *rough draft*. I have a number of amazing people providing feedback that will get incorporated and it still has to go through the copy edit phase as well. But even as a rough draft, it should be pretty good. 😉

Here is the url: http://my.safaribooksonline.com/9780596807276

Note: the day after I posted this, Safari accidentally sent an email to Safari subscribers saying that the book is now in print. That was what we call a SNAFU. Not in print yet. Still a few more months.

RIA Services and Entity Framework POCOs

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))