If there is a class which works as a data access layer, and provides the functionality of CRUD operations for entities, Which version is the best practice when considering performance & Multi threaded environment (i.e methods of this class are called by multiple threads simultaneously . .). . .
Version 1:
DbContext created at class level, shared by all the methods . .
class EmployeeService{
private DbContext db=new DbContext();
public Employee GetEmployee(int id)
return db.Employees.Find(id);
}
public void AddEmployee(Employee employee){
db.Employees.Add(employee);
db.SaveChanges();
}
}
Version 2:
DbContext for each method call . .
class EmployeeService{
public Employee GetEmployee(int id){
using(DbContext db=new DbContext()){
return db.Employees.Find(id);
}
}
public void AddEmployee(Employee employee){
using(DbContext db=new DbContext()){
db.Employees.Add(employee);
db.SaveChanges();
}
}
}
UPDATE: May be the question posted is too generic in scope which leads several points to consider.
The point of interest is, the cost of instantiating DbContext object. Can it be created per request (Version 2) or is it heavy weight object and better to create few instances and share them across different calls (Version 1)
There's even a third approach based on manual or automatic dependency injection:
public interface ISomeService
{
// Interface members
}
public class SomeService : ISomeService
{
public SomeService(DbContext dbContext)
{
DbContext = dbContext;
}
private DbContext DbContext { get; }
}
Then, SomeService
won't be the responsible of defining the life-time of injected DbContext
, but it's an external class who does it.
That way, your service focuses on doing just what's meant to do (working with the domain and reading/writing data).
Depending on the execution environment, you'll want different DbContext
life-styles: per service instance, per request, per thread... There're a lot of choices here depending on the case.
Perhaps you're not considering another scenario: a shared transaction between two or more services. You would need to transfer the responsibility of instantiating DbContext
to an upper layer, and then you would inject same DbContext
on all participating services, and you would confirm or abandon the whole transaction globally.