Reusing DbContext object created in Spring.Net across controllers and actions - database

What is better? Or maybe - is the following a good practice?
I use Spring.net to create an instance of DbContext and then inject it into every controller for use in actions. The object is a singleton. Sometimes I get an exception which says that the "The ObjectContext instance has been disposed.." I suspect that this might be the reason, however this is not repeatable, and so far my application is only used by me during the development.
Now, would it be better to create a DbContext in every controller class and reuse in it's actions; or maybe create the DbContext object in every action itself; or just set it in the Spring config not to be a singleton, so it is created every time it is being accessed?

It is best to inject your dbcontext using request scope. That way, the context is created on the start of a request and disposed at the end. During the request you'll have a db context available so that it can handle lazy loaded objects for you.
When you register as a singleton, the dbcontext is shared for all requests, which most of the time isn't what you want. For instance, it might be that it hold a reference to all your loaded objects, potentially loading the entire db into memory.

Related

Context Lifetime on a WinForms app .Net6 with Dependency Injection

I am having some issues with context lifetime on my .NetCore 6 win forms application. In summary, I have a button that when clicked calls a repository which then retrieves a record from my DB and displays one value from that record in a text field. This works ok until that value changes in the database. Further clicks of the button continue to display the old value.
This is how I register my context in the winforms app
services.AddDbContext<MyContext>(b => b.UseSqlServer(connectionString));
I then register my services like this:
services.AddScoped<IMyRepo, MyRepo>();
I guess this is an issue where the form is long running and never disposes the context, hence why the result is always the same until the form is closed and reopened with a fresh context.
I am using this in my repo to force a new result each time, however is seems like a bit of a mission to do this for every request to the DB I make...
_entities.Entry(log).Reload();
Is there a cleaner way I can do this without having to do the reload?
Honestly, I wouldn't use the MS IoC AddDbContext for WinForms/WPF. There probably is a way to have it play nice with some form of lifetime scope, but I'm honestly not aware of one. I don't use it for web projects either, simply because it scopes the DbContext to the request and I like to have a bit more control over the lifetime of the DbContext in some situations. (Dealing with poisoned contexts for instance)
For web and WPF I've used a Unit of Work pattern called the DbContextScope to manage the DbContext and relationship with the Repositories. The idea being that the consumers use an injected DBContextScopeFactory to create a DbContextScope (wrapping one or more DbContext instances) and the Repositories accept an injected DbContexScopeLocator to gain access to a requested DbContextScope.
The original EF6 implementation was by Medhi El Gueddari (https://github.com/mehdime/DbContextScope || https://www.nuget.org/packages/Mehdime.Entity)
For EF Core 6: (https://www.nuget.org/packages/Zejji.DbContextScope.EFCore6)
Alternatively if the scope of a DbContext can be contained within the repository calls themselves (tracked entities don't need to be passed outside of the repository) then you could also just use an injected DbContextFactory class to provide DbContext instances on demand. The advantage of a UoW pattern like above is that you have control over the scope the DbContext instance(s) live so multiple operations can be committed together or rolled back. The DbContext instance is available between multiple repositories if needed.

Ionic/angular provider/service - singleton - single instance?

I have read that service(angular)/provider(ionic) can be specific to components, or can be shared by components by registering it at module level. I understand that this is singleton concept that is single instance shared by all components. My question is - suppose the service/provider has code that fetches data from db based on logged in userid, then in this case, how does a single instance concept differentiate between all users using the app? Bit confused on this aspect.
As far As i know singleton means a single component/service that have content that can be shared with any other page/component/controller/...
but all that is happening in one instance of the app.
Example:
lets say in our project we have 3 pages with controllers: page1.html, ctrl1.js, page2.html, ctrl2.js, page3.html, ctrl3.js
We also have 1 service: service1.js
In service1.js we have a function called getUserName()
The concept of singleton will allow getUserName() to be called from all 3 controllers. if the service is not sigleton this means it will be related to one controller/page, so if service1.js is only related to ctrl1.js, the function getUserName() cannot be called from ctrl2.js
Important: all this is happening in one instance of the app, singleton does not mean that the service is SHARED between all running instances of the app.
That being said, if you are using your service to get data from the database based on some parameters, it is the logic you implemented that decide what data will be returned.

In angular how do i share data on a session basis

So my understanding is that factories are singletons so any stateful data for a session would be ill placed here.
My next point of call was a service which returns a new instance of the service when injected however I am unsure how I would share one instance of the service to multiple controllers.
Is this an accepted way to solve this issue or does angular provide a better way?
My current use case is that I have a view with some partial views (each partial has it's own controller) and a modal window which takes in a row id and will display data dependant on that data.
I need to be able to share a instance of the service (or equivalent) across these controllers but on a per session basis.
How is this best done?
The singleton exists for one user and loaded SPA. Thats what you would usually refer to as a session. Its a good place to store data that needs to be accessed by different controllers.

Don't understand the need for $cacheFactory if Factories are singletons

I'm relatively new to AngularJs and I'm trying to build a single page application with it. My application runs within a content management site. I have 3 factories for user, group and site functions.
I'm interested in using angular's $cacheFactory but I'm not sure what the benefit is if my data remains in the factory since it's a singleton.
For example, my user factory has an object called allUsers. This object is used through my application for different views. Intuitively, it seems like it's something that should be cached but I'm having a hard time understanding why since this object is in the user factory which can be access from any of my controllers.
CacheFactory is a factory:
The purpose of the Factory Method pattern is to define an interface for creating an object but deferring instantiation of the object to subclasses.
which creates new instances each time an object of its type is created, unlike a Singleton:
The intent of the Singleton pattern is to ensure that only one instance of a class is loaded, and that the instance provides a global point of access.
In Angular, the CacheFactory offers the following benefits over other solutions:
Caches can be injected into a filter, unlike controller scopes
Caches can be enumerated
Caches can be easily destroyed or redefined
Caches are not tied to digest data binding, unlike controller scopes
Caches are not tied to browser permissions, unlike cookies or localStorage/sessionStorage
I'm not sure what the benefit is if my data remains in the factory
CacheFactory offers the following features:
'should create cache with defined capacity'
'should blow away the entire cache via removeAll and start evicting when full'
'should correctly refresh and evict items if operations are chained'
But CacheFactory also has the following unexpected behaviors:
'should purge the next entry if the stalest one was removed'
'should only decrement size when an element is actually removed via remove'
References
Deep dive into JSF patterns
Factory method and MVC
AngularJS Source: cacheFactorySpec.js
Why is OOP Difficult?
DCOM and CORBA Side by Side, Step By Step, and Layer by Layer

Unity to return new instance of service

I have come across a bit of a problem while using Unity and WPF. The scenario is I have a WPF application which follows the MVVM design pattern. A have a module called ViewKDI. Within this module I have a service called ViewKDIService, the ViewKDIService service utilises another service called UserService.
Every time I load the module ViewKDI I want Unity to return me a new instance of both the ViewKDIService and the UserService.
I have put the below in the shell bootstrapper:
Container.RegisterType<IUserService, UserService>();
In the ViewKDI module I have put the following:
Container.RegisterType<IViewKDIService, ViewKDIService>();
Each time the ViewKDI module loads the ViewKDIService constructor is called. However the UserService constructor is only called the first time, this means that I am not getting a new instance of UserService.
I require unity to give me a new instance of UserService too so that I can manage this session separately from the rest of the application.
Any ideas?
Thanks
Faisal
Unity's default behaviour is to create a new instance of each object each time one is requested, so you shouldn't be seeing this behaviour.
From what I can gather from the source code and MSDN documentation (this is a good read), you can specify a "lifetime manager" object when you register a type to tell Unity how the type should be constructed and cached. Using the TransientLifetimeManager (which essentially does no caching) will cause Unity to re-create the class each time. So try this:
Container.RegisterType<IUserService, UserService>(new TransientLifetimeManager());
... and see if it creates a new UserService each time.

Resources