views:

400

answers:

3

In CarTrackr project, It use some technique that creates only 1 repository instance for all request in Asp.net Mvc website and uses UnityControllerFactory class to manage all repository instanes(send to requested controller).

Is there any benefit to using single repository instance when compare with creating new repository instance every request?

I know, it may improve overall performance. But, Does it cause any transcation problem?

partial Global.asax

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        RegisterRoutes(RouteTable.Routes);
        RegisterDependencies();
    }

    protected static void RegisterDependencies() {
        IUnityContainer container = new UnityContainer();

        // Registrations
        container.RegisterType<IUserRepository, UserRepository>(new ContextLifetimeManager<IUserRepository>());
        container.RegisterType<ICarRepository, CarRepository>(new ContextLifetimeManager<ICarRepository>());

        // Set controller factory
        ControllerBuilder.Current.SetControllerFactory(
            new UnityControllerFactory(container)    
        );
    }
}

partial CarController.cs

[Authorize]
public class CarController : Controller
{
    private IUserRepository UserRepository;
    private ICarRepository CarRepository;

    public CarController(IUserRepository userRepository, ICarRepository carRepository)
    {
        UserRepository = userRepository;
        CarRepository = carRepository;
    }
}

Thanks,

A: 

Using the new ContextLifetimeManager());, the lifetime of a repository is limited to one request. This means that evry request each repository is instantiated (if needed) and destroyed once a response has been sent to the client.

maartenba
What's different between DefaultControllerFactory and ContextLifetimeManager? Because both of them will create new Controller instance when user request.
Soul_Master
The factory is the thing leveraging the container. That is, its the thing responsible for calling the container.Resolve() to get a new instance of IController based on the configuration. The ContextLifetimeManager is setting the scope at which the instance will be cached. Caching the instance makes it so the container doesn't recreate the object as long as an instance exists in scope.
TheDeeno
+3  A: 

Creating a repository instance per request by itself shouldn't cause any performance issue; the repository is often pretty shallow, and when it needs to access data things like connection pooling minimise the cost of establishing actual connections. Object creation is astonishingly cheap, especially for short-lived things like web requests where the object gets collected while still in "generation zero".

As to whether to have a single repository or a repository per instance - that depends on the repository ;-p

The biggest question is: is your repository thread safe? If not: one per request.

Even if it is though; if your repository itself keeps something like a LINQ-to-SQL DataContext (that you synchronize somehow), then you have big problems if you keep this long-term, in particular with the identity manager. You'll quickly use a lot of memory and get stale results. Far form ideal.

With a single repository instance, you will probably also end up with a lot of blocking trying to get thread safety. This can reduce throughput. Conversely, the database itself has good ways of achieving granular locks - which is particularly useful when you consider that often, concurrent requests will be looking at separate tables etc - so no blocking at the database layer. This would be very hard to do just at the repository layer - so you'd probably have to synchronize the entire "fetch" - very bad.

IMO, one per request is fine in most cases. If you want to cache data, do it separately - i.e. not directly on the repository instance.

Marc Gravell
From my example, Can CLR call same method of the repository instance at the same time(from difference request)? Next, What's difference between creating instance per web request by ContextLifetimeManager and creating instance by Asp.net Mvc framework?
Soul_Master
I guess that CLR can call any method at the same time but error might occur when method try to lock same layer of database at the same time.
Soul_Master
The CLR won't stop you (unles you synchronize it yourself) from calling into a method on the same instance - but you need to be careful about the state inside the instance... is it thread safe? What happens if one thread is updating the state of the repository instance while another reads it? Re the RDBMS - that will usually have much better (i.e. safer) locking; isolation is part of the RDBMS's day job, after all - so I wouldn't expect an exception unless you manage to deadlock yourself.
Marc Gravell
+2  A: 

I think you're misunderstanding whats happening with the ContextLifeTimeManager. By passing the manager into the Register() method your telling Unity to set the caching scope for your repository instance to HttpContext.

It is actually incorrect to say:

It use some technique that creates only 1 repository instance for all request in Asp.net > Mvc website

There is not a repository singleton. Unity is creating one for each request. It sounds like this is actually your desired behavior.

When the manager's scope is set to HttpContext the container looks to HttpContext for an existing instance of the requested type (in this case, your repository). Since the HttpContext is fresh on each request, the container will not have this instance, thus a new one will be created.

When you ask:

Is there any benefit to using single repository instance when compare with creating new repository instance every request?

No.

As far as transaction problems: Threading will def be an issue. The CarRepository appears to be using Linq2Sql or Linq2Entities. Its ctor requires an active datacontext. DataContext is NOT thread safe. If the datacontext is being stored at a scope higher than the current request, there will be problems.

TheDeeno
You told me that I need to create only 1 DbConnection per web request. Moreover, 1 or multiple repositories/controller are not important because they are personal coding style. Right?
Soul_Master
Sorry, first pass was made in a rush. I edited to address the question more clearly now. Make sense?
TheDeeno
And btw, both the pts I may have miscommunicated to you are false. There are cases where you need more than 1 conn per request (but normally 1 is fine). And not using more than 1 controller is also a mistake for any site that has more than 1 feature. As for repositories - they are not part of the MVC paradigm and thus, a coding style. You don't need any if you so desire.
TheDeeno
Upvoted cause of making me feel dumb. :)
Arnis L.