views:

251

answers:

1

Currently for ASP.Net stuff I use a request model where a context is created per request (Only when needed) and is disposed of at the end of that request. I've found this to be a good balance between not having to do the old Using per query model and not having a context around forever. Now the problem is that in WPF, I don't know of anything that could be used like the request model. Right now it looks like its to keep the same context forever (Which can be a nightmare) or go back to the annoying Using per query model that is a huge pain. I haven't seen a good answer on this yet.

My first thought was to have an Open and Close (Or whatever name) situation where the top level method being called (Say an event handling method like Something_Click) would "open" the context and "close" it at the end. Since I don't have anything on the UI project aware of the context (All queries are contained in methods on partial classes that "extend" the generated entity classes effectively creating a pseudo layer between the entities and the UI), this seems like it would make the entity layer dependent on the UI layer.

Really at a loss since I'm not hugely familiar with state programming.

Addition:

I've read up on using threads, but the problem I have with a context just sitting around is error and recovery.

Say I have a form that updates user information and there's an error. The user form will now display the changes to the user object in the context which is good since it makes a better user experience not to have to retype all the changes.

Now what if the user decides to go to another form. Those changes are still in the context. At this point I'm stuck with either an incorrect User object in the context or I have to get the UI to tell the Context to reset that user. I suppose that's not horrible (A reload method on the user class?) but I don't know if that really solves the issue.

A: 

Have you thought about trying a unit of work? I had a similar issue where I essentially needed to be able to open and close a context without exposing my EF context. I think we're using different architectures (I'm using an IoC container and repository layer), so I have to cut up this code a bit to show it to you. I hope it helps.

First, when it comes to that "Something_Click" method, I'd have code that looked something like:

using (var unitOfWork = container.Resolve<IUnitOfWork>){

   // do a bunch of stuff to multiple repositories, 
   // all which will share the same context from the unit of work

   if (isError == false)    
      unitOfWork.Commit();
}

In each of my repositories, I'd have to check to see if I was in a unit of work. If I was, I'd use the unit of work's context. If not, I'd have to instantiate my own context. So in each repository, I'd have code that went something like:

if (UnitOfWork.Current != null)
{
    return UnitOfWork.Current.ObjectContext;
}
else
{
    return container.Resolve<Entities>();
}

So what about that UnitOfWork? Not much there. I had to cut out some comments and code, so don't take this class as working completely, but... here you go:

public class UnitOfWork : IUnitOfWork
{
    private static LocalDataStoreSlot slot = Thread.AllocateNamedDataSlot("UnitOfWork");
    private Entities entities;

    public UnitOfWork(Entities entities)
    {
     this.entities = entities;
     Thread.SetData(slot, this);
    }

    public Entities ObjectContext
    {
     get
     {
      return this.Entities;
     }
    }

    public static IUnitOfWork Current
    {
     get { return (UnitOfWork)Thread.GetData(slot); }
    }

    public void Commit()
    {
     this.Entities.SaveChanges();
    }

    public void Dispose()
    {
     entities.Dispose();
     Thread.SetData(slot, null);
    }
}

It might take some work to factor this into your solution, but this might be an option.

Darren