I want to make sure I'm disposing my EF dbContext objects.
Currently I'm using static methods to invoke EF crud operations to keep all the data layer stuff black boxed and out of the controllers.
The example below I have one method the returns an IQueryable and uses a Using statment which causes an exception when the query tries to run on a disposed context object.
The other doesn't use the Using statement and works fine but is it getting disposed?
Should I just return IEnumerable instead of IQueryable?
public class MyContext : DbContext
{
public MyContext() : base("MyConnectionString")
{
Database.SetInitializer<EFContext>(null);
}
public DbSet<User> Users { get; set; }
public DbSet<Role> Roles { get; set; }
}
public class Data
{
// Fails when IQuerable tried to run against a disposed MyContext object
public static T Get<T>(params string[] joins)
{
using (var context = new MyContext())
{
return context.Get<T>(joins);
}
}
// Works fine but when is it disposed?
public static T Get<T>(params string[] joins)
{
return new MyContext().Get<T>(joins);
}
}
public ActionResult GetUser(int id = 0)
{
var data = Data.Get<User>();
return View("Users", model);
}
The issue is not about using IQueryable or IEnumerable. You have the exception because by returning IQueryable or IEnumerable, you're not executing the LINQ. You just openned a connection to your Database then close after configuring your query.
To solve this, you need to execute the LINQ query by calling ToList, ToArray, Single[OrDefault], First[OrDefault] etc... extension methods.
Because you're using Web Application, it is a best practice to have one instance of your DbContext in the whole life of your web request. I recommend you to use DI (Dependency Injection), it will help you a lot. You can try Simple Injector which is very simple DI.
If you're not able to use DI so just follow this steps but take a time to learn about DI please :) :
When a web request arrives, store a new instance of your DbContext into HttpContext.Items collections.
In your methods, just retrieve the stored DbContext from HttpContext.Items and use it.
When the web request is terminating, just dispose the DbContext.
Related
In my asp mvc Framework project, using EF, I have some objects (from classes) whose fields store data coming from my database.
My question is :
How to populate these fields, or manage methods of these objects using a dbcontext variable ?
Sol 1: Is it better to use each time I need a connection with db in my classes with the instruction (using (resource), see below ) ?
Sol 2: Is it betterI to code a singleton class to use one instance of the context ?
Sol 3: Or should I use another way for the links beetween my classes and the database ?
What is the best method considering performances and code quality.
Thanks for your attention .
Solution 1
public class Test
{
private T1 a;
private T2 b;
public Test()
{}
public void CreateFrom (int id)
{
using (var db=new WebApplicationMVCTest.Models.dbCtx())
{
a=db.T1s.Find(id);
b= db.T2s.Find(a.id2);
}
}
Solution 2:
public class DbSingleton
{
private static dbCtx instance;
private int foo;
private DbSingleton ()
{}
public static dbCtx Current
{
get
{
if (instance == null)
{
instance = new dbCtx();
}
return instance;
}
}
public static void Set (dbCtx x)
{
if (instance==null)
{
instance = x;
}
}
}
For a web project, never use a static DbContext. EF DbContexts are not thread safe so handling multiple requests will lead to exceptions.
A DbContext's lifespan should only be as long as it is needed. Outside of the first time setup cost when a DbContext is used for the first time, instantiating DbContexts is fast.
My advice is to start simple:
public ActionResult Create(/* details */)
{
using (var context = new AppDbContext())
{
// do stuff.
}
}
When you progress to a point where you learn about, and want to start implementing dependency injection applications then the DbContext can be injected into your controller / service constructors. Again, from the IoC container managing the DbContext, the lifetime scope of the Context should be set to PerWebRequest or equivalent.
private readonly AppDbContext _context;
public MyController(AppDbContext context)
{
_context = context ?? throw new ArgumentNullException("context");
}
public ActionResult Create(/* details */)
{
// do stuff with _context.
}
The gold standard for enabling unit testing would be injecting a Unit of Work pattern and considering something like the Repository pattern to make your dependencies easier to unit test.
The best advice I can give you starting out with EF and MVC is to avoid the temptation to pass Entities between the controller (server) and the UI. (views) You will come across dozens of examples doing just this, but it is a poor choice for performance, it also hides a LOT of land mines and booby traps for both performance, exceptions, and data security issues. The most important detail is that when the UI calls the controller passing what you expect will be an entity, you are not actually getting an entity, but a de-serialized JSON object cast to an entity. It is not an entity that is tracked by the DbContext handling the request. Instead, get accustomed to passing view models (serializable data containers with the data the view needs or can provide) and IDs + values where the controller will re-load entities to update the data only as needed.
In my .NET Core 3 WebAPI project, I have the following, simple method call:
[HttpGet("ViewerRoles")]
public IAsyncEnumerable<ViewerRole> GetViewList() {
using var db = new MpaContext();
return db.ViewerRoles.AsAsyncEnumerable();
}
This throws me an ObjectDisposedException. AsAsyncEnumerable() is relatively new and I can't find any appropriate examples of how to use it in such situations. Should I just remove the using keyword and the Entity Framework database connection magically disposes itself? Or is there another trick?
You have two options. Either enumerate the IAsyncEnumerable inside your GetViewList method:
[HttpGet("ViewerRoles")]
public async IAsyncEnumerable<ViewerRole> GetViewList()
{
using var db = new MpaContext();
await foreach (var item in db.ViewerRoles.AsAsyncEnumerable().ConfigureAwait(false))
{
yield return item;
}
}
...or install the System.Interactive.Async package and use the static AsyncEnumerableEx.Using method:
[HttpGet("ViewerRoles")]
public IAsyncEnumerable<ViewerRole> GetViewList()
{
return AsyncEnumerableEx.Using(() => new MpaContext(),
db => db.ViewerRoles.AsAsyncEnumerable());
}
Here is the signature of the AsyncEnumerableEx.Using method:
public static IAsyncEnumerable<TSource> Using<TSource, TResource>(
Func<TResource> resourceFactory,
Func<TResource, IAsyncEnumerable<TSource>> enumerableFactory)
where TResource : IDisposable;
Unfortunately it seems that there is no online documentation available for this library.
You should implement IDisposable on your controller, and dispose the DbContext in the controller's Dispose method
using statement in this case scopes your dbContext to function scope, so the correct way would be to enumerate before returning from action, otherwise you returning something what is cannot be correctly evaluated later (after function returned and context disposed)
alternatively, you can move dbContext creation to controller's scope, which is can be request scope (it is not that hart to implement via framework's DI and DI will take care about everything with IDisposable and scoped to request "magically")
I have also found the approach to use the method Response.RegisterForDispose(). But I still do not know which approach is the most promising.
[HttpGet("ViewerRoles")]
public IAsyncEnumerable<ViewerRole> GetViewList() {
MpaContext db = new MpaContext();
Response.RegisterForDispose(db);
return db.ViewerRoles.AsAsyncEnumerable();
}
I see all answers have its own point and all of them true. So, I can only make some clarifications on them.
You should choose a moment of disposing object depending on how you expose it. For example, your original code implicitly exposes MpaContext db to AspNet pipeline and you can't dispose db until netcore done his work with it. So, you can register disposing of it by Response.RegisterForDispose(), as you mentioned. But, it's uncommon because you don't have access to Response usually - you can do this only inside Controller, or if you share it with Controller dependencies, but it will rise code complexity.
That's why you can avoid this by relying on lifetime of controller. Since, it's in request scope it will live until response was sent. So, you can create your db as controller dependency and hold it within a property. Also you should implement IDisposable on controller.
public class RoleController : IDisposable
{
private MpaContext DbContext { get; }
public RoleController()
{
DbContext = new MpaContext();
}
[HttpGet( "ViewerRoles" )]
public IAsyncEnumerable<ViewerRole> GetViewList()
{
return DbContext.ViewerRoles.AsAsyncEnumerable();
}
public void Dispose()
{
DbContext.Dispose();
}
}
In this case you can stick to this pattern even if you will move your logic to some other class (as it supposed to be, I believe). But still, if you manually create disposable objects you should care about disposing them. That's the moment when DI comes to help.
By using DI you can forget about disposing objects that was created by DI. DI will call Dispose() on any dependency when lifecycle of it ends. Register your MpaContext by calling AddDbContextPool<MpaContext>() or AddDbContext<MpaContext>() if you use EntityFramework under MpaContext. With this approach you will get clear code of your controller.
public class RoleController
{
private MpaContext DbContext { get; }
public RoleController( MpaContext dbContext )
{
DbContext = dbContext;
}
[HttpGet( "ViewerRoles" )]
public IAsyncEnumerable<ViewerRole> GetViewList()
{
return DbContext.ViewerRoles.AsAsyncEnumerable();
}
}
If you don't want to expose MpaContext to controller and want to create it manually inside GetViewList(), you can still enumerate result within the action method and dispose context as Theodor Zoulias answered. But why would you, if you can simply delegate this work to DI.
Given the following scenario...
I am concerned about two things...
1) Is it okay to inject a provider into a business model object? - like I did with the Folder implementation because I want to load Sub-folders on demand.
2) Since I am injecting the DbContext in the Sql implementation of IFolderDataProvider, the context could be disposed or it could live on forever, therefore should I instantiate the context in the constructor?
If this design is incorrect then someone please tell me how should business models be loaded.
//Business model.
interface IFolder
{
int Id { get; }
IEnumerable<IFolder> GetSubFolders();
}
class Folder : IFolder
{
private readonly int id_;
private readonly IFolderDataProvider provider_;
public Folder(int id, IFolderDataProvider provider)
{
id_ = id;
provider_ = provider;
}
public int Id { get; }
public IEnumerable<IFolder> GetSubFolders()
{
return provider_.GetSubFoldersByParentFolderId(id_);
}
}
interface IFolderDataProvider
{
IFolder GetById(int id);
IEnumerable<IFolder> GetSubFoldersByParentFolderId(int id);
}
class SqlFolderDataProvider : IFolderDataProvider
{
private readonly DbContext context_;
public SqlFolderDataProvider(DbContext context)
{
context_ = context;
}
public IFolder GetById(int id)
{
//uses the context to fetch the required folder entity and translates it to the business object.
return new Folder(id, this);
}
public IEnumerable<IFolder> GetSubFoldersByParentFolderId(int id)
{
//uses the context to fetch the required subfolders entities and translates it to the business objects.
}
}
Is it okay to inject a provider into a business model object? - like I did with the Folder implementation because I want to load Sub-folders on demand.
Yes, how else would you be able to call the provider and get the data?
However, the suffix DataProvider is very confusing because it is used for the provider that you use to connect to the database. I recommend changing it to something else. Examples: Repository, Context.
Since I am injecting the DbContext in the Sql implementation of IFolderDataProvider, the context could be disposed or it could live on forever, therefore should I instantiate the context in the constructor?
It won't necessarily live on forever. You decide its life span in your ConfigureServices function when you're adding it as a service, so you can change its scope from Singleton to whatever you like. I personally set the scope of my DBContext service to Transient and I also initiate it there with the connection string:
services.AddTransient<IDbContext, DbContext>(options =>
new DbContext(Configuration.GetConnectionString("DefaultDB")));
I then open and close the database connection in every function in my data layer files (you call it provider). I open it inside a using() statement which then guarantees closing the connection under any condition (normal or exception). Something like this:
public async Task<Location> GetLocation(int id) {
string sql = "SELECT * FROM locations WHERE id = #p_Id;";
using (var con = _db.CreateConnection()) {
//get results
}
}
Is it okay to inject a provider into a business model object
Yes if you call it "business" provider :). Actually do not take too serious all this terminology "inject", "provider". Till you pass (to business model layer's method/constructor) interface that is declared on business model layer (and document abstraction leaks) - you are ok.
should I instantiate the context in the constructor?
This could be observed as an abstraction leak that should be documented. Reused context can be corrupted or can be shared with another thread and etc -- all this can bring side effects. So developers tend to do create one "heavy" object like dbContext per "user request" (that usually means per service call using(var context = new DbContext()), but not always, e.g. Sometimes I share it with Authentication Service Call - to check is the next operation allowed for this user). BTW, DbContext is quite quick to create so do not reuse it just for "optimization".
I am looking for some advice on the best way to re-structure an existing C# Console Application that I have written.
The application utilises Entity Framework for the Data coupled with the Repository pattern. I am also using Ninject for DI.
The issue I am facing is as follows:
I have a class, say ClassA, which has a Repository passed in through the constructor. The repository constructor takes in a DbContext. Ninject is currently handling all of this for me.
public class ClassA
{
private IRepository Repository;
public ClassA(IRepository repostitory)
{
Repository = repository;
}
public void Process()
{
var RV = Function1();
Function2(RV);
Function3(RV);
}
private IList<ClassB> Function1()
{
//Populate database using Repository and return list of objects
var items = //Call External Web Service to get list of Items
foreach(var item in items)
{
Repository.AddEntry(item);
}
return Repository.Items.ToList();
}
private void Function2(IList<Item> items)
{
//Long running process maybe 20/30 mins.
}
private void Function3(IList<Item> items)
{
//Remove objects in list from database via the Repository.
foreach(var item in items)
{
Repository.DeleteEntry(item);
}
}
}
public class Repository : IRepository
{
private DbContext DbContext;
public IQueryable<Item> Items
{
get { return DbContext.Items; }
}
public Repository(DbContext dbContext)
{
DbContext = dbContext;
}
void AddEntry(Item item)
{
DbContext.Items.Add(item);
DbContext.SaveChanges();
}
void DeleteEntry(Item item)
{
DbContext.Items.Remove(item);
DbContext.SaveChanges();
}
}
ClassA then has a process function that works through a series of 3 private functions.
Only functions 1 and 3 need access to the Repository, as 1 populates the database via the Repository and then returns an in memory collection. Function 2 uses this collection, after which function 3 deletes records from the database via the Repository.
Function 2 can take several minutes to complete and the behaviour I am noticing is that when function 3 calls the database I receive a "DbContext has been disposed" error. It has not been disposed in any of my code but it seems another process running on the same SQL server is causing this.
In an attempt to work around this I want to be able to dispose of the Repository after function 1 and then use a new one for function 3, so in essence wrap the code in function 1 & 3 inside a using statement. This is when my head starts to hurt when trying to figure out this scenario whilst utilising Ninject.
What should I be passing in to ClassA as part of the constructor to allow me to create on the fly Repostitories? Do I need some sort of Factory pattern or Unit of Work pattern?
Any help or thoughts gratefully received.
Thanks
pf79
You can inject your DbContext as a factory instead of an instance perse, take a look at this: https://github.com/vany0114/EF.DbContextFactory
http://elvanydev.com/EF-DbContextFactory/
There is an extension to Ninject to do that in a very easy way, just calling the method kernel.AddDbContextFactory<YourContext>(); also you need to change your repository by receiving a Func<YourContext>
I'm using LINQ2SQL to handle my database needs in a ASP. Net MVC 3 project. I have a separate model which contains all my database access in its own class as follows:
public class OperationsMetricsDB
{
public IEnumerable<client> GetAllClients()
{
OperationsMetricsDataContext db = new OperationsMetricsDataContext();
var clients = from r in db.clients
orderby r.client_name ascending
select r;
return clients;
}
public void AddClient(client newClient)
{
OperationsMetricsDataContext db = new OperationsMetricsDataContext();
db.clients.InsertOnSubmit(newClient);
db.SubmitChanges();
}
I have about 50 different methods in this class which all create and then destroy a copy of my DataContext. My reasoning was that this way would save memory because it would destroy the DataContext after I use the connection and free up that memory. However, I have a feeling that it may be better to use one copy the dataContext and keep it open instead of disposing and reestablishing the connection over and over again. e.g
public class OperationsMetricsDB
{
OperationsMetricsDataContext db = new OperationsMetricsDataContext();
public IEnumerable<client> GetAllClients()
{
var clients = from r in db.clients
orderby r.client_name ascending
select r;
return clients;
}
public void AddClient(client newClient)
{
db.clients.InsertOnSubmit(newClient);
db.SubmitChanges();
}
What is the best practice on this?
I personally use the Unit of Work pattern in conjunction with Repositories for this.
The UnitOfWork creates and manages the DataContext. It then passes the context to each repository when requested. Each time the caller wants to do a new set of operations with the database, they create a new UnitOfWork.
The interfaces would look something like:
public interface IUnitOfWork
{
IRepository<T> GenerateRepository<T>();
void SaveChanges();
}
public interface IRepository<T> where T : class
{
public IQueryable<T> Find();
public T Create(T newItem);
public T Delete(T item);
public T Update(T item);
}
That ensures that the context's lifespan is exactly one Unit of Work long (which is longer than a single operation but shorter than the lifespan of the application).
Its not recommended to cary a datacontext a long time with you. So you are on the right path. It uses connection pooling as far as i know, so the performance hit of creating more than one datacontext in an applications lifetime is not too serious.
But i would not create a new context instance for every single method call of your data class.
I prefer to use it in a unit of work style. Within a web application the processing of a http request can be seen as a unit of work.
So my advice is to create one datacontext instance for the lifetime of on http request and dispose it afterwards.
One context per request is usually fine for most applications.
http://blogs.microsoft.co.il/blogs/gilf/archive/2010/05/18/how-to-manage-objectcontext-per-request-in-asp-net.aspx