Search code examples
c#entity-frameworksql-server-cecode-first

Architecture with SQL Server CE


I have to build a number of small independent applications, that can be copied to an USB device and run from there out of the box. So I was thinking to use WPF, that uses EF code first to connect to a SQL Server CE database.

My question is about what architecture I should use. Although the apps are standalone, I would still like to decouple UI from domain from data, to have a clean separation of layers. But I also don't want to make it too complex.

So, I want to have a UI layer (WPF/MVVM) that uses the underlying domain layer (domain objects with domain logic) and repositories (that use EF code first).

My question is: what pattern should I use to make EF work in this case? Is there somewhere an example that demonstrates how to implement CRUD operations in such scenario? For example, should I create one context and leave it open; or should I implement the unit of work pattern and attach objects to other context if needed?

Or would you do it in a totally different way?

Thanks for the advice!


Solution

  • The EF context should be open for as short time as possible. Preferably use it within a using statement.

    private static void ApplyItemUpdates(SalesOrderDetail originalItem,
        SalesOrderDetail updatedItem)
    {
        using (AdventureWorksEntities context =
            new AdventureWorksEntities())
        {
            context.SalesOrderDetails.Attach(updatedItem);
            // Check if the ID is 0, if it is the item is new. 
            // In this case we need to chage the state to Added.
            if (updatedItem.SalesOrderDetailID == 0)
            {
                // Because the ID is generated by the database we do not need to
                // set updatedItem.SalesOrderDetailID.
                context.ObjectStateManager.ChangeObjectState(updatedItem, System.Data.EntityState.Added);
            }
            else
            {
                // If the SalesOrderDetailID is not 0, then the item is not new
                // and needs to be updated. Because we already added the 
                // updated object to the context we need to apply the original values.
                // If we attached originalItem to the context 
                // we would need to apply the current values:
                // context.ApplyCurrentValues("SalesOrderDetails", updatedItem);
                // Applying current or original values, changes the state 
                // of the attached object to Modified.
                context.ApplyOriginalValues("SalesOrderDetails", originalItem);
            }
            context.SaveChanges();
        }
    }
    

    There is a method called Attach, which attachs entities to a context:

    private static void AttachRelatedObjects(
        ObjectContext currentContext,
        SalesOrderHeader detachedOrder,
        List<SalesOrderDetail> detachedItems)
    {
        // Attach the root detachedOrder object to the supplied context.
        currentContext.Attach(detachedOrder);
    
        // Attach each detachedItem to the context, and define each relationship
        // by attaching the attached SalesOrderDetail object to the EntityCollection on 
        // the SalesOrderDetail navigation property of the now attached detachedOrder.
        foreach (SalesOrderDetail item in detachedItems)
        {
            currentContext.Attach(item);
            detachedOrder.SalesOrderDetails.Attach(item);
        }
    }
    

    http://msdn.microsoft.com/en-us/library/bb896271.aspx