RavenDB with IoC/DI - IDocumentStore or I(Async)DocumentSession? - dependency-injection

I googled a bit and searched this forum before posting this, since I presumed it had been beaten to death - but since I didn't see any results that seemed clearly asking this, I figured I'd give it a shot. There's a pretty high chance it's been answered before, but I didn't stumble upon a clear page about it.
When using dependency injection, which is considered the better practice? Injecting the entire IDocumentStore and then spawning a session from it as needed, or injecting the appropriate IDocumentSession or IAsyncDocumentSession?
In the past, I've injected IAsyncDocumentSession everywhere - but it's come up that I actually need to use a non async session in a few places. This got me to thinking if I was just approaching injecting Raven wrong altogether.
So, using the IDocumentStore might be like ...
public AsHandler(IDocumentStore store) { RavenStore = store; }
private IDocumentStore RavenStore { get; set; }
public async Task Handle() {
using(var session = RavenStore.OpenAsyncSession()) {
... // do stuff with an async session
}
}
But then the more specific session usecases would appear such as ...
public AsHandler(IAsyncDocumentSession session) { RavenSession = session; }
private IAsyncDocumentSession RavenSession { get; set; }
public async Task Handle() {
// do stuff with an async session
}
or respectively ...
public AsHandler(IDocumentSession session) { RavenSession = session; }
private IDocumentSession RavenSession { get; set; }
public async Task Handle() {
// do stuff with a non-async session
}
Is there even any difference other than preference? My initial thought is that using the IDocumentSession and IAsyncDocumentSession is better lifecycle management, but I could be wrong.
I am using .NET Core 2.0.3 with StructureMap with Raven DB 4.0 (40023) specifically, but I would posit that this could apply to any configuration and any version.

Not sure this has changed with 4.0 but so far the creation of the DocumentStore was considered a rather expensive/heavy operation and therefore the suggested approach is to create it only once per application (singleton; for futher details please see RavenDb Documentation).
Sessions on the other hand are rather cheap to create and therefore can be created as needed.
You could still inject both objects (store and session) with DI and just use different lifecycles (singleton vs. transient).
Of course you can also setup DI to provide either the sync- or the asnyc-version of the session as needed.

Related

HttpContext is null when injected into a singleton dependency

I'm looking to create a global class in my Blazor application that contains a function that gets the user's Department through the user's username which I get from Windows authentication but I can't seem to access the HttpContextAccessor through my global class. It acts like it has access to HttpContext when I inject it but when it runs, I get the error
System.NullReferenceException: 'Object reference not set to an instance of an object.'
and the accessor is null when you look at it in the local variables.
I've done a lot of googling but couldn't find anything that melded well with what I'm doing and my current knowledge of how these things work.
Here's my global class:
public class Global
{
[Inject]
IHttpContextAccessor HttpContextAccessor { get; set; }
public string Identity;
public string Department;
public Global()
{
Identity = HttpContextAccessor.HttpContext.User.Identity.Name;
CalculateDepartment(Identity)
}
private void CalculateDepartment (string identity) {
//Calculate what department the person is in based on user ID
Department = CalculatedDepartment;
}
}
Here is my startup:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor(o => o.DetailedErrors = true);
services.AddTelerikBlazor();
services.AddHttpContextAccessor();
services.AddSingleton<Global>();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.ApplicationServices.GetRequiredService<Global>();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
endpoints.MapControllers();
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
}
}
Google said to use services.AddScoped<Global> but I found that this didn't work with my CalculateDepartment function and when I used services.AddSingleton<Global> it worked so I kept it that way.
It appears to be doing this to anything I try to inject in this way into this file. I can inject things into any other page but not this class apparently. There were a few people simply saying to inject it into the constructor but that didn't help me much as I'm fairly new to this and I couldn't get the examples that I found of that to work. That could be the solution though, maybe I just need to do it in a way that would work. There could just be a better way of making a global class too.
Based on what I've surmised from your question - your looking to get access to the the HttpContext in Blazor Server. If so, then this code - credit to Robin Sue - gets the context for you:
// Server Side Blazor doesn't register HttpClient by default
// Thanks to Robin Sue - Suchiman https://github.com/Suchiman/BlazorDualMode
if (!services.Any(x => x.ServiceType == typeof(HttpClient)))
{
// Setup HttpClient for server side in a client side compatible fashion
services.AddScoped<HttpClient>(s =>
{
// Creating the URI helper needs to wait until the JS Runtime is initialized, so defer it.
var uriHelper = s.GetRequiredService<NavigationManager>();
return new HttpClient
{
BaseAddress = new Uri(uriHelper.BaseUri)
};
});
}
If not then ignore the answer!
It turns out that I was unable to access anything that was injected through my constructor so I did some research and according to this website:
https://blazor-university.com/dependency-injection/injecting-dependencies-into-blazor-components/
Dependencies are injected after the Blazor component instance has been created and before the OnInitialized or OnInitializedAsync lifecycle events are executed. This means we cannot override our component’s constructor and use those dependencies from there, but we can use them in the OnInitialized* methods.
So basically I just can't use injected dependencies at all in my constructor. I've got to find another way to do this then! I'll update this when I find another way to do it if I don't just give up and move on.
Edit:
I ended up using a (imo) not great work around where I created a method in Global.cs that set the username string to whatever was put into it. Then I used the fact that my shared layouts are used at all times and can access the username through the use of <AuthorizeView> so I just set the username using the method that I created in one of my layouts like this:
<AuthorizeView>
<Authorized>
#{
Global.SetUserName(context.User.Identity.Name);
}
</Authorized>
</AuthorizeView>
So yeah, not ideal but it works and for now that's my goal.

Unit of work + repository + service layer with dependency injection

I am designing a web application and a windows service and want to use the unit of work + repository layer in conjunction with a service layer, and I am having some trouble putting it all together so that the client apps control the transaction of data with the unit of work.
The unit of work has a collection of all repositories enrolled in the transaction along with commit and rollback operations
public interface IUnitOfWork : IDisposable
{
IRepository<T> Repository<T>() where T : class;
void Commit();
void Rollback();
}
The generic repository has operations that will be performed on the data layer for a particular model (table)
public interface IRepository<T> where T : class
{
IEnumerable<T> Get(Expression<Func<T, bool>> filter = null, IList<Expression<Func<T, object>>> includedProperties = null, IList<ISortCriteria<T>> sortCriterias = null);
PaginatedList<T> GetPaged(Expression<Func<T, bool>> filter = null, IList<Expression<Func<T, object>>> includedProperties = null, PagingOptions<T> pagingOptions = null);
T Find(Expression<Func<T, bool>> filter, IList<Expression<Func<T, object>>> includedProperties = null);
void Add(T t);
void Remove(T t);
void Remove(Expression<Func<T, bool>> filter);
}
The concrete implementation of the unit of work uses entity framework under the hood (DbContext) to save the changes to the database, and a new instance of the DbContext class is created per unit of work
public class UnitOfWork : IUnitOfWork
{
private IDictionary<Type, object> _repositories;
private DataContext _dbContext;
private bool _disposed;
public UnitOfWork()
{
_repositories = new Dictionary<Type, object>();
_dbContext = new DataContext();
_disposed = false;
}
The repositories in the unit of work are created upon access if they don't exist in the current unit of work instance. The repository takes the DbContext as a constructor parameter so it can effectively work in the current unit of work
public class Repository<T> : IRepository<T> where T : class
{
private readonly DataContext _dbContext;
private readonly DbSet<T> _dbSet;
#region Ctor
public Repository(DataContext dbContext)
{
_dbContext = dbContext;
_dbSet = _dbContext.Set<T>();
}
#endregion
I also have a service classes that encapsulate business workflow logic and take their dependencies in the constructor.
public class PortfolioRequestService : IPortfolioRequestService
{
private IUnitOfWork _unitOfWork;
private IPortfolioRequestFileParser _fileParser;
private IConfigurationService _configurationService;
private IDocumentStorageService _documentStorageService;
#region Private Constants
private const string PORTFOLIO_REQUEST_VALID_FILE_TYPES = "PortfolioRequestValidFileTypes";
#endregion
#region Ctors
public PortfolioRequestService(IUnitOfWork unitOfWork, IPortfolioRequestFileParser fileParser, IConfigurationService configurationService, IDocumentStorageService documentStorageService)
{
if (unitOfWork == null)
{
throw new ArgumentNullException("unitOfWork");
}
if (fileParser == null)
{
throw new ArgumentNullException("fileParser");
}
if (configurationService == null)
{
throw new ArgumentNullException("configurationService");
}
if (documentStorageService == null)
{
throw new ArgumentNullException("configurationService");
}
_unitOfWork = unitOfWork;
_fileParser = fileParser;
_configurationService = configurationService;
_documentStorageService = documentStorageService;
}
#endregion
The web application is an ASP.NET MVC app, the controller gets its dependencies injected
in the constructor as well. In this case the unit of work and service class are injected. The action performs an operation exposed by the service, such as creating a record in the repository and saving a file to a file server using a DocumentStorageService, and then the unit of work is committed in the controller action.
public class PortfolioRequestCollectionController : BaseController
{
IUnitOfWork _unitOfWork;
IPortfolioRequestService _portfolioRequestService;
IUserService _userService;
#region Ctors
public PortfolioRequestCollectionController(IUnitOfWork unitOfWork, IPortfolioRequestService portfolioRequestService, IUserService userService)
{
_unitOfWork = unitOfWork;
_portfolioRequestService = portfolioRequestService;
_userService = userService;
}
#endregion
[HttpPost]
[ValidateAntiForgeryToken]
[HasPermissionAttribute(PermissionId.ManagePortfolioRequest)]
public ActionResult Create(CreateViewModel viewModel)
{
if (ModelState.IsValid)
{
// validate file exists
if (viewModel.File != null && viewModel.File.ContentLength > 0)
{
// TODO: ggomez - also add to CreatePortfolioRequestCollection method
// see if file upload input control can be restricted to excel and csv
// add additional info below control
if (_portfolioRequestService.ValidatePortfolioRequestFileType(viewModel.File.FileName))
{
try
{
// create new PortfolioRequestCollection instance
_portfolioRequestService.CreatePortfolioRequestCollection(viewModel.File.FileName, viewModel.File.InputStream, viewModel.ReasonId, PortfolioRequestCollectionSourceId.InternalWebsiteUpload, viewModel.ReviewAllRequestsBeforeRelease, _userService.GetUserName());
_unitOfWork.Commit();
}
catch (Exception ex)
{
ModelState.AddModelError(string.Empty, ex.Message);
return View(viewModel);
}
return RedirectToAction("Index", null, null, "The portfolio construction request was successfully submitted!", null);
}
else
{
ModelState.AddModelError("File", "Only Excel and CSV formats are allowed");
}
}
else
{
ModelState.AddModelError("File", "A file with portfolio construction requests is required");
}
}
IEnumerable<PortfolioRequestCollectionReason> portfolioRequestCollectionReasons = _unitOfWork.Repository<PortfolioRequestCollectionReason>().Get();
viewModel.Init(portfolioRequestCollectionReasons);
return View(viewModel);
}
On the web application I am using Unity DI container to inject the same instance of the unit of work per http request to all callers, so the controller class gets a new instance and then the service class that uses the unit of work gets the same instance as the controller. This way the service adds some records to the repository which is enrolled in a unit of work and can be committed by the client code in the controller.
One question regarding the code and architecture described above. How can I get rid of the unit of work dependency at the service classes? Ideally I don't want the service class to have an instance of the unit of work because I don't want the service to commit the transaction, I just would like the service to have a reference to the repository it needs to work with, and let the controller (client code) commit the operation when it see fits.
On to the windows service application, I would like to be able to get a set of records with a single unit of work, say all records in pending status. Then I would like to loop through all those records and query the database to get each one individually and then check the status for each one during each loop because the status might have changed from the time I queried all to the time I want to operate on a single one. The problem I have right now is that my current architecture doesn't allow me to have multiple unit of works for the same instance of the service.
public class ProcessPortfolioRequestsJob : JobBase
{
IPortfolioRequestService _portfolioRequestService;
public ProcessPortfolioRequestsJob(IPortfolioRequestService portfolioRequestService)
{
_portfolioRequestService = portfolioRequestService;
}
The Job class above takes a service in the constructor as a dependency and again is resolved by Unity. The service instance that gets resolved and injected depends on a unit of work. I would like to perform two get operations on the service class but because I am operating under the same instance of unit of work, I can't achieve that.
For all of you gurus out there, do you have any suggestions on how I can re-architect my application, unit of work + repository + service classes to achieve the goals above?
I intended to use the unit of work + repository patterns to enable testability on my service classes, but I am open to other design patterns that will make my code maintainable and testable at the same time while keeping separation of concerns.
Update 1
Adding the DataContext class that inheris from EF's DbContext where I declared my EF DbSets and configurations.
public class DataContext : DbContext
{
public DataContext()
: base("name=ArchSample")
{
Database.SetInitializer<DataContext>(new MigrateDatabaseToLatestVersion<DataContext, Configuration>());
base.Configuration.ProxyCreationEnabled = false;
}
public DbSet<PortfolioRequestCollection> PortfolioRequestCollections { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Configurations.Add(new PortfolioRequestCollectionConfiguration());
base.OnModelCreating(modelBuilder);
}
}
If your purpose for using Unit of Work (UoW) was for testability, you took the wrong path. Unit of work does nothing for testability. Its main purposes is to provide atomic transactions to disparate data sources, provide UoW functionality to a data layer that doesn't already provide it, or to wrap an existing UoW in a way that makes it more easily replaceable... something which you've nullified by using the generic repository (this tightly couples it to Entity Framework anyways).
I suggest you get rid of the Unit of Work completely. Entity Framework is already a UoW. Even Microsoft has changed their mind and no longer recommend UoW with EF.
So, if you get rid of UoW, then you can just use repositories to wrap your EF queries. I don't suggest using a generic repository, as this leaks your data layer implementation all over your code (something your UoW was already doing), but rather create Concrete repoTsitories (these can use generic repositories internally if you like, but the generic repository should not leak outside of your repository).
This means your service layer takes the specific concrete repository it needs. For instance, IPortfolioRepository. Then you have a PortfolioRepository class that inherits from IPortfolioRepository which takes your EF DbContext as a parameter that gets injected by your Depndency Injection (DI) framework. If you configure your DI container to instance your EF context on a "PerRequest" basis, then you can pass the same instance to all your repositories. You can have a Commit method on your repository that calls SavesChanges, but it will save changes to all changes, not just to that repository.
As far as Testability goes, you have two choices. You can either mock the concrete repositories, or you can use the built-in mocking capabilities of EF6.
I have been through that hell hole myself and here's what I have done:
Ditch the UoW completely. EF's DBContext is a UoW basically. No point in re-inventing the wheel.
Per MSDN:
DbContext Class
Represents a combination of the Unit-Of-Work and Repository patterns
and enables you to query a database and group together changes that
will then be written back to the store as a unit.
Service layer + Repo layer seemed like a good choice. However, repos are always a leaky abstraction and espcially when DBContext's DbSet are the equivalent of repositories.
Then when the need for a Windows service arises, things become muddied further with another layer now. Throw async or background processing in the mix, and things quickly start leaking.
If you ask my 2 cents, I would say go with the service layer + EF, one wrapping business logic, the other one wrapping UOW/Repository pattern.
Alternatively, and for Windows Services especially, I'm finding that moving to a command-query based approach works better.
Not only it helps testability, it also helps in asynchronous tasks where I don't have to worry about keeping the DBContext alive even after the request has ended (DBContext is now tied with the command handler and stays alive as long as the async command stays alive).
Now if you've recently ended up digesting all those facts about UOW/Repository pattern, then surely, just even reading about Command-Query pattern will make your mind hurt. I have been down that path but trust me, its worth the time to at least look into it and giving it a try.
These posts may help:
Meanwhile... on the query side of my architecture
Meanwhile... on the command side of my architecture
If you're brave enough (after digesting thru CQRS), then take a look at MediatR which implements the Mediator pattern (which basically wraps up command-query with notifications) and allows to work via pub-sub. The pub-sub model suits nicely in the Windows Service and services layer.

Identity 2.0.0 in MVC5 architecture advice

I'm trying to integrate the recently released ASP.NET Identity 2.0.0 into a 3-layer MVC application. I'm not sure I'm going in the correct direction. I can see two approaches to take.
In the first approach, I've gone with integrating Identity into each logical layer. Having some technical issues integrating but still developing.
In the second approach, go with a a self-contained encapsulated assembly dedicated for security.
I've gone with approach 1 at the moment, but questioning it all. Also, any other approaches to take?
Approach 1
Web
Startup.cs
/App_Start/Startup.Auth
/Controllers/Account
/Controllers/Manage
/Controllers/RolesAdmin
/Controllers/UserAdmin
/ViewModels
/Views
Business Logic
/Service/AccountService
/Service/ApplicationRoleManager
/Service/ApplicationUserManager
/Service/EmailService
/Service/SmsService
/Service/SignInHelper
Data
ApplicationDbContext
ApplicationUser
So, I've simply taken Identity and plugged it into each layer I see that fits.
I've put most of the log in the Business Logic layer, as it doesn't belong in the Web and there no 'real' database code for it to belong in the Data layer.
Side-issue: I'm a bit uncomfortable that in the Web/App_Start/Startup.Auth, I have to instantiate the Busness Logic object to call
app.CreatePerOwinContext(ApplicationDbContext.Create);
in the Data layer. I've yet to think about this more. This is another issue (but I see it is related to the architecture I've chosen).
Approach 2
Creating an assembly purely for Security which contains no layers, i.e. simply plug in Identity 2.0.0 into this one assembly. And my application can reference this. It goes against the layers though. But it encapsulates security. Given security objects can (or should) be resident throughout the application lifetime, this doesn't seem like a bad idea at all. Haven't thought about about scalability though.
I have taken approach 1, and when creating the context I have a helper class that I attempt to get the context from HttpContext.Current.["DbActiveContext"] and use it if it exists, if not create then new one, and use a single context for the entire application. So you do not end up with one context for aspnet idenity and another one for the rest of the app. It looks like you are trying to use a repository pattern in the first approach, if that is the case, then your model for your identity should be in the DB layer, and for full repository pattern, you should be using dependency injection when creating your objects, by doing so, you will not have a dependency until the object is created at run time.
namespace Data.Common
{
public class ConnectionHelper : IConnectionHelper
{
private ApplicationDbContext _context;
public ApplicationDbContext Context
{
get
{
if (_context == null && HttpContext.Current.Items["DbActiveContext"] != null)
{
_context = (ApplicationDbContext)HttpContext.Current.Items["DbActiveContext"];
}
else if (_context == null && HttpContext.Current.Items["DbActiveContext"] == null)
{
_context = new ApplicationDbContext();
HttpContext.Current.Items.Add("DbActiveContext", _context);
}
return _context;
}
set { _context = value; }
}
}
}
Also if you want to use the usermanager in the service layer with DI you can do something like:
public UserController()
: this(
new ApplicationUserManager(new UserStore<ApplicationUser>(new ConnectionHelper().Context)),
new UserService())
{
}
With the UserService signature like:
public class UserService
{
private readonly IRepository<ApplicationUser> _user;
private readonly UserManager<ApplicationUser> _userManager;
public UserService(IRepository<ApplicationUser> user,
UserManager<ApplicationUser> userManager)
{
_user = user;
_userManager = userManager;
}
public UserService()
: this(
new Repository<ApplicationUser>(new ConnectionHelper()),
new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ConnectionHelper().Context)))
{
}
I hope this helps you!

MVC3 tool using Entity Framework caching issues with Ninject

I've got a new MVC 3 application which is showing some issues when modifying data manually in the Database.
The tool is still in development and once in a while I want to change my user's teamId. When I do so, I have to kill the Web development Server and run it again otherwise the queries don't pick the new teamId.
Same thing when I publish the tool to IIS, if I ever modify something on the database, I need to either copy over the 'bin' folder again or stop the application and re-run it.
When I modify data from the application itself, I have no problems.
This is how my Ninject looks like:
public class NinjectControllerFactory : DefaultControllerFactory
{
private IKernel kernel = new StandardKernel(new TrackerServices());
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
return null;
return (IController)kernel.Get(controllerType);
}
private class TrackerServices : NinjectModule
{
public override void Load()
{
var context = new TrackerEntities();
Bind<IUserRepository>().To<UserRepository>().WithConstructorArgument("context", context);
}
}
}
My Interface:
public interface IUserRepository : IRepository<User>
{
User GetByName(string name);
}
my Implementation:
public User GetByName(string login)
{
var userLogin = _misc.GetUsername(login);
return _context.Users.Where(x => x.Login == userLogin).Single();
}
And my Index Action
public ActionResult Index()
{
var teamid = (int)_users.GetByName("myName").TeamId;
This has never happened before, but this tool is the first one I'm using with Ninject. I'm wondering if there's a relation between my problem and using a repository?
There are two issues that are combining to create this problem:
The way you've created your context is causing it to effectively be a singleton.
Entity Framework will not automatically check for a new version of an entity which the context is already tracking.
To solve this, I would recommend that you recreate your repository once per request (there won't be a significant performance hit for this, as it's fairly lightweight), by using this binding:
Bind<IUserRepository>().To<UserRepository>().InRequestScope();
Ninject should be able to create your TrackerEntities context automatically, but if not (or if you want to make it clear), you can use the following binding:
Bind<TrackerEntities>().ToSelf().InRequestScope(); (The InRequestScope is not really required here, as the default transient scope should be okay).
You could also go down the road of forcing a refresh of the entity (using ObjectContext.Refresh()), but that's probably not a great idea because you'd have to do it explicitly for each entity.

What is the scope of my Ninject injected ObjectContext in my custom MembershipProvider (using Request scope)?

I use Entity Framework 4 and ASP.NET MVC 3. I made a custom membership provider and use Ninject to inject an EFAccountRepository into it (Bound IAccountRepository to EFAccountRepository).
This account repository has an ObjectContext injected into it. I also use this repository (and others) in my controllers. For this reason when I bound IContext to my ObjectContext, I set the scope to "per request" so the ObjectContext only lives in one request and is shared between the repositories.
I am sometimes get the following error when trying to log in:"The ObjectContext instance has been disposed and can no longer be used for operations that require a connection."
I wonder how often the membership provider gets instantiated. I injected the repository into the membership provider by marking the repository property with [Inject] and calling Kernel.Inject in the Application_Start function in the global.asax file.
If the provider gets instantiated more than once I would have to inject again I suppose. However, I don't get a null pointer exception, so I don't think that's it.
Update 1
Here's some code:
MyNinjectModule.cs
public override void Load()
{
Bind<IMyContext>().To<MyObjectContext>().InRequestScope();
// put bindings here
Bind<IAccountRepository>().To<EFAccountRepository>
}
Global.asax
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
var kernel = new StandardKernel(new MyNinjectModule());
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory(kernel));
kernel.Inject(Membership.Provider);
}
MyMembershipProvider.cs
[Inject]
public IAccountRepository accountRepository { get; set; }
public override bool ValidateUser(string username, string password)
{
// I get the exception here.
return (from a in accountRepository.Accounts
where a.UserName == username
&& a.Password == password
select true).SingleOrDefault();
}
EFAccountRepository.cs
private readonly IMyContext context;
public EFAccountRepository(IMyContext context)
{
this.context = context;
}
public IQueryable<Account> Accounts
{
get { return context.Accounts; }
}
MyObjectContext.cs
public class MyObjectContext : ObjectContext, IMyContext
{
public IObjectSet<Account> Accounts { get; private set; }
public FlorenceObjectContext()
: this("name=DomainModelContainer")
{
}
public FlorenceObjectContext(string connectionString)
: base(connectionString, "DomainModelContainer")
{
Accounts = CreateObjectSet<Account>();
}
}
PS: I'm always open to comments on my code in general ;).
The exception says that you are incorrectly handling disposing of your context. Somewhere you call context.Dispose (or have context in using) but after that you want to use context again which is not possible because context is already disposed. If you are using per request context you must dispose context only once at the end of request processing (when you are sure that no code will use the context).
You didn't specify a scope for your EFAccountRepository binding so it defaults to .InTransientScope(). This means a new instance of the object will be created each time you resolve the IAccountRepository [refer to https://github.com/ninject/ninject/wiki/Object-Scopes ].
Also, transient scope objects
are automatically garbage collected as soon as there are no references to them [Ninject doesn't cache them]
are not automatically disposed by anyone
In contrast, you bound MyObjectContext to IObjectContext .InRequestScope(). This means it will be reused when you are in the same HTTP request handling operation.
Also, a request scope object
won't be garbage collected until your http request is done
might be automatically disposed once the HTTP request is done, if it's IDisposable. [Not sure precisely when, but from other questions I have seen I suspect it depends on the version of Ninject]
Now, ObjectContext is IDisposable, so it seems reasonable to conclude that
an object reference to the IObjectContext exists, and you are using the IObjectContext outside of the HTTP request which it was created in.
Ninject has automatically disposed of it, since the HTTP request has completed.
In order to solve the issue, you need to figure out why your object context object reference is surviving so long, and consider either eliminating the long-livedness... or removing its dependency on short-lived (request-scoped) objects.
[note clearly the question already has an accepted answer, but I think the accepted answer was kind of hard to understand.]

Resources