This thread looks to be a little on the old side and therefore may no longer be relevant. Please see if there is a newer thread on the subject and ensure you're using the most recent build of any software if your question regards a particular product.
This thread has been locked and is no longer accepting new posts, if you have a question regarding this topic please email us at support@mindscape.co.nz
|
Hi In MVC3 I've taken your FilmFestival code http://www.mindscapehq.com/staff/jeremy/index.php/2009/03/aspnet-mvc-part1/ and am using the same data access methodology. It works! Question: Is there a more recommended way now in LS3 / MVC3? Global.asax: internal static readonly LightSpeedContext<MvcPvAdmin.Models.LightSpeedModel1UnitOfWork> LightSpeedDataContext = new LightSpeedContext<MvcPvAdmin.Models.LightSpeedModel1UnitOfWork>("Default"); Base class controller helper:
public class MvcPvAdminController : Controller { private const string UNIT_OF_WORK = "__UnitOfWork__"; private UnitOfWorkScopeBase<MvcPvAdmin.Models.LightSpeedModel1UnitOfWork> _unitOfWorkScope;
public UnitOfWorkScopeBase<MvcPvAdmin.Models.LightSpeedModel1UnitOfWork> UnitOfWorkScope { get { if (_unitOfWorkScope == null && System.Web.HttpContext.Current != null) { _unitOfWorkScope = System.Web.HttpContext.Current.Items[UNIT_OF_WORK] as PerRequestUnitOfWorkScope<MvcPvAdmin.Models.LightSpeedModel1UnitOfWork>; }
if (_unitOfWorkScope == null) { _unitOfWorkScope = new PerRequestUnitOfWorkScope<MvcPvAdmin.Models.LightSpeedModel1UnitOfWork>(MvcApplication.LightSpeedDataContext);
if (System.Web.HttpContext.Current != null) { System.Web.HttpContext.Current.Items[UNIT_OF_WORK] = _unitOfWorkScope; } }
return _unitOfWorkScope; } }
protected MvcPvAdmin.Models.LightSpeedModel1UnitOfWork uow { get { return UnitOfWorkScope.Current; } }
protected override void OnResultExecuted(ResultExecutedContext filterContext) { if (_unitOfWorkScope != null) { _unitOfWorkScope.Dispose(); }
base.OnResultExecuted(filterContext); }
public new void Dispose() { if (_unitOfWorkScope != null) { _unitOfWorkScope.Dispose(); }
base.Dispose(); } }
and Controller:
public class PeopleController : MvcPvAdminController { // // GET: /People/ public ActionResult Index() { return View(uow.People.ToList()); }
// // GET: /People/Details/5
public ActionResult Details(int id) { Person person = uow.People.Single(p => p.Id == id); return View(person); } |
|
|
No, thats still the recommended way of managing scoping, the only thing you may want to review depending on your object lifetimes is disposing the UnitOfWork via the EndRequest event rather than at the end of the Result execution, however for most apps you can leave it as is.
Jeremy |
|
|
Not sure if my question is better served in a new thread, but... Is it anyway possible to work with multiple database context using the pattern above? The requirements only came up recently, for a multi-tenanted application in order to better manage database growth (multiple database with the same schema). |
|
|
Yes, you will need to write your own class to accomodate this however. The PerRequestUnitOfWorkScope class stores the current UnitOfWork object under HttpContext.Current.Items with a specifically named key, so instantiating more of these (or another with a different UOW type) would simply overwrite the existing one - so to store more than one UOW you just need to extend this accordingly. Have a look at this thread which gives a code example from one of our other customers who had to solve this: http://www.mindscapehq.com/forums/Thread.aspx?PostID=5406 We also have a similar approach for our website where we hold the PerRequest object itself in the Items collection rather than the UOW, the structure of it looks like this: public class PerRequestUnitsOfWork
Jeremy |
|
|
Thanks Jeremy, I understand the logic but the mechanics still escapes me... As I'm actually using an IoC/DI + repository pattern, all instantiation of the repository class is done up-front (via bootstrap / app start) and I'm just a little unsure how exactly do I 'switch' to another context / dynamically choose a context within the business logic? Note: My UoW class is setup within the base controller. Is there any example that you can give me or can you give me further pointers? Thanks in advance. |
|
|
You cannot "switch" a context once you have a UnitOfWork instantiated, the UnitOfWork is created from a context, so if you wanted to switch you would be wanting to create a seperate UnitOfWork. Do you need to use many units of work from many contexts within the scope of a single request or are you simply trying to have a context which has a more dynamic connectionstring aspect?
Jeremy
|
|
|
It is both. We need to run two UoW in the scope of a single request, but the connection string for the second UoW needs to be determined dynamically. e.g. In the 1st UoW it calls the 'Admin' database and get the tenant information, and it uses this info to connect to the particular database zone / instance which contains the tenant data. |
|
|
Then you will need to create your second UnitOfWork based on a context which you are configuring at runtime with the appropriate connection string. You could set up the context object in advance, but just set the ConnectionString property once you have it and then you would be able to create a UnitOfWork instance for it. I am assuming you are using the PerRequestUnitOfWorkScope to get access to a UnitOfWork within your repository instances you are injecting. So if you were still wanting to manage this via a custom PerRequestUnitOfWorkScope object, you would want to set up a method which you can use to configure the second context instance by passing it the ConnectionString. If we take the earlier example from this post and modify it so UnitOfWork3 would be the dynamically configured one then we could do something like: public void ConfigureContext3(string connectionString) { Context3.ConnectionString = connectionString; }
and probably add a check into the gettor for UnitOfWork3 to guard against accidental access of the UOW if the connection string had not been configured otherwise you will get an exception thrown from the associated ADO.NET provider when we try and create the connection object when using the UnitOfWork. public UnitOfWork3 Three if (String.IsNullOrEmpty(Context3.ConnectionString)) { throw new InvalidOperationException("The dynamic context has not been correctly configured, ensure you call ConfigureContext3()"); } _unitOfWork3 = Context3.CreateUnitOfWork();
Jeremy |
|