Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework Context - I'm Stuck!

Tags:

asp.net-mvc

Ok, so i have asked a few questions on this before, but I really am just having a hrad time understanding this.

I am using the Service/Repository/EF 4 w/Pocos approach, and I have Ninject setup and injecting the controllers with the services but I am trying to figure out where to inject the context?

I want to be able to use multiple services on the controllers which in turn might access multiple repositories using the same context so all the changes would be persisted at once.

I studied the UnitOfWork pattern, but I don't understand how the MVC (controllers) would implement this as they only know of the service layer and the domain entities.

Edit

As Mohamed suggested below, inject the context into the repositories and then use a per request instance of it. How do you configure the binding in the MVC app? I would assume something like this:

Bind(Of IContext).To(MyDataContext)

Problem is, the MVC app knows nothing of the context, right?

Edit 2

Public Class ProductController
    Private _Service As IProductService

    Public Sub New(Service As IProductService)
        _Service = Service
    End Sub

End Class

Public Class NinjectWebModule

    Public Sub New()
        Bind(Of IProductService).To(ProductService)
    End Sub

End Class

Public Interface IProductService

End Interface

Public Class ProductService
    Implements IProductService

    Private _Repository As IRepository(Of Product)

    Public Sub New(Repository As IRepository(Of Product))
        _Repository = Repository
    End Sub

End Class

Public Class NinjectServiceModule

    Public Sub New()
        Bind(Of IRepository(Of Product)).To(EFRepository(Of Product))
    End Sub

End Class

Public Interface IRepository(Of T As Class)

End Interface

Public Class EFRepository(Of T As Class)
    Implements IRepository(Of T)

    Private _UnitOfWork As MyUnitOfWork

    Public Sub New (UnitOfWork As IUnitOfWork)
        _UnitOfWork = UnitOfWork
    End Sub

End Class

Public Class NinjectRepositoryModule

    Public Sub New()
        Bind(Of IUnitOfWork).To(EFUnitOfWork).InRequestScope()
    End Sub

End Class

Public Interface IUnitOfWork
    Sub Commit()
End Interface

Public Class EFUnitOfWork()
    Implements IUnitOfWork

    Public Property Context As MyContextType

    Public Sub New()
        _Context = New MyContextType
    End Sub

End Class

I would then register all three modules from the MVC app?

like image 608
Sam Avatar asked Mar 07 '11 05:03

Sam


2 Answers

Components you need:

  1. Repository(s) (generic or specific)
  2. Unit Of Work
  3. Services
  4. Controllers

What each is:

  1. Repository: executes queries against supplied context
  2. Unit of Work: wraps Entity Framework ObjectContext
  3. Services: calls methods on Repository
  4. Controllers: calls methods on Services, and calls "Commit" on Unit of Work.

With that in line, you Controller's ctor should look like this:

public ProductController(IUnitOfWork unitOfWork, IProductService productService)

You need the UoW because you mentioned you want to make changes across multiple repositories (a fairly common scenario). So by passing the UoW (which is the ObjectContext under the hood) to the Repositories, you can enable that.

Use a DI container to setup the Unit of Work as Http Context scoped.

like image 75
RPM1984 Avatar answered Sep 18 '22 02:09

RPM1984


How about injecting ObjectContext in repository classes? and use single instance per request?

Update

See this example ASP.NET MVC 3 Application using Ninject, Entity Framework 4 Code-First CTP 5, Patterns

Update 2

This example is for NHibernate session, but it is exactly the same idea with EF ObjectContext or LinqToSQL DataConext or similar stuff. Really good example. Check it and tell me what you think.

http://www.itslet.nl/?p=904

Update 3

The place where you define your DI bindings HAS to know about all the concrete implementations of course. If you really want your MVC code to not know about the context, you either

  • put that code in new project that does know about it,
  • or use XML for doing the bindings (there is documentation in Ninject site itself on how to do that, but it's not the default intended use of this particular DI container),
  • or use Ninject Modeules (basically this means splitting your bindings, so, you can have one module that does the context bidning in the same project as the context, and the MVC just uses all discoverable Ninject Modules for binding).

This is one example of using Ninject Modules: What is the intention of Ninject modules?

like image 40
Meligy Avatar answered Sep 20 '22 02:09

Meligy