Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Not sure how to use Dependency Injection + Repository Pattern + Unit Of Work Pattern with a WinForm application

(apologies for the Wall Of Text... :) )

Summary

Using Dependency Injection with my Winfor application is creating a large number of Repository Context's. I'm not sure if the way i'm using this is right or wrong, or what the common practice is.

Details

In the last 6 odd months, I've been making ASP.NET MVC applications that impliment the Unit O fWork pattern with the Repository Pattern. On top of this, I've been using an Dependency Injection on all of these web applications with some success.

So this is an example of me wiring up my repository.

public EntityFrameworkRepositoryRegistry() 
{ 
    For<IUnitOfWork>() 
            .HybridHttpOrThreadLocalScoped() // Lifecycle of the object.
            .Use<SqlServerContext>()  // My EF Context.
            .Ctor<string>("connectionString").Is("name=SqlServer_EF")
            .Ctor<string>("defaultContainerName").Is("Entities"); 
 
    // Ayende's EFProf application :) 
    EntityFrameworkProfiler.Initialize();      

    Scan(x => 
        { 
            x.TheCallingAssembly(); 

            x.ExcludeNamespaceContainingType<Fake.FakeContext>(); 

            x.WithDefaultConventions(); 
        } 
    );    
} 

Ok - works great. Main thing to note here is that

  • I'm assuming the Lifecycle is the correct one for a Web scenario.
  • The context will only exists once, per REQUEST that hits the webserver.

kewl.

Now, for my WinForm application, i initially created a single Unit Of Work object (no dependency injection, just yet) and kept passing that baby around to all the services (and then to the repositories).

For this win application, it hits the DB to find out all the text files it needs to parse. (eg. 25 files). Then, for each file, it creates a new Parser, reads each line and chucks the parsed data into a db table. Fine.

Problem was, this concext was being shared amoungst ALL Parsers, which was seriously throwing up errors all over the shop.

So then i added some Dependency Injection and uses that registry code above. Sorta same thing - lots of serious errors. This is because ONE context was again created for the single thread -> the winform.

So, i now tweaked the Registry of the Context to following :-

public EntityFrameworkRepositoryRegistry(bool isForTheWeb) 
{ 
    if (isForTheWeb) 
    { 
        For<IUnitOfWork>() 
            .HybridHttpOrThreadLocalScoped() 
            .Use<SqlServerContext>() 
            .Ctor<string>("connectionString").Is("name=SqlServer_EF") 
            .Ctor<string>("defaultContainerName").Is("Entities"); 
    } 
    else 
    { 
        For<IUnitOfWork>() 
            .Use<SqlServerContext>() 
            .Ctor<string>("connectionString").Is("name=SqlServer_EF") 
            .Ctor<string>("defaultContainerName").Is("Entities"); 
    } 
    
    EntityFrameworkProfiler.Initialize(); 
    
    Scan(x => 
    { 
        x.TheCallingAssembly(); 
        
        x.ExcludeNamespaceContainingType<Fake.FakeContext>(); 
        x.WithDefaultConventions(); 
    }); 
} 

So for a WinForm application, it now doesn't set the Lifecycle. This then created around 160 or so context's i think! (But it didn't really error, either).

So, i'm not sure if this is the right way to do things.

So my app, in effect, has 25 different timers going, to check a file every .. say .. 10 secs. If there's new data, it parsers it. Otherwise, come back in 10 secs.

Should each one of these files that gets parsed, be it's own thread? and then create a context per thread? (which i feel is similar to the web scenario). Or is this fine? I know it's a lot of context's, but each context doesn't mean a live connection to the db .. and with connection pooling, this shouldn't really be a problem.

The reason it has so many contexts, is becuase of the following code... (and these are seperate Constructors for some of the Repository classes...)

public SqlServerContext(string, string); 
public GameFileRepository (IUnitOfWork); 
public LogEntryRepository(IUnitOfWork); 
public AlertRepository(IUnitOfWork); 
... etc.. 

and for the main Service...

public PunkBusterParser(IUnitOfWork, IGameFileRepositry, 
ILogEntryRepository, ILoggingService); 

so the service requires an UoW and each repository also requires one ..which means a new one is getting created for each one.

I'm sure i haven't structured this correctly...

Any suggestions would be sincerely grateful!

like image 264
Pure.Krome Avatar asked Feb 21 '10 00:02

Pure.Krome


People also ask

What is the unit of work responsible for when used with entity Framework?

The Unit of Work holds all the entities involved in a Business logic into a single transaction and either commits the transaction or rolls it back.

What is difference between dependency injection and Repository pattern?

They really aren't comparable a repository is something you can inject via dependency injection. The aim of DI is to make your application loosely coupled. Rather than specify a concrete implementation you can specify an interface that defines a contract that an implementation must fulfil.

Why should you use a Repository pattern for your project?

The benefit of using The Repository Pattern in this instance is that you can write the Repository interface at the beginning of the project without really thinking about the actual technical details of how you are going to store your data.


1 Answers

This article by Ayende might provide you with some insight about how to manage your unit of work in a desktop application (The general idea is to use a 'session per presenter') : http://msdn.microsoft.com/en-us/magazine/ee819139.aspx

like image 194
jeroenh Avatar answered Sep 17 '22 13:09

jeroenh