I have the following piece of database transaction wrapper written :
public class ExampleWrapper : IDisposable
{
public DbContextTransaction Transaction { get; set; }
public DcatContext DatabaseContext { get; set; }
public ExampleWrapper ()
{
DatabaseContext = new someContext();
Transaction = DatabaseContext.Database.BeginTransaction();
}
public void Dispose()
{
Transaction.Dispose();
}
public void Commit()
{
Transaction.Commit();
}
public void RollBack()
{
Transaction.Rollback();
}
}
I have code something similar to the following in my DAL :
public async Task<Object> Retrieve(string Id)
{
using (var context= new SomeContext())
{
return Context.Object.Find(id);
}
}
I am trying to keep the business layer separate from any Entity Framework dependency and that's the reason for the wrapper Class. If I am trying to do a transaction from the BLL for example:
using(var wrapper = new ExampleWrapper())
{
//make calls to the DAL
something.Retrieve(Id)
}
My question is I am initializing the Dbcontext twice (Here while creating a transaction, as well as in the DAL) . Is there any suggestion any of you have how I can do this better? .
PS: Just using retrieve in a transaction as an example .
You can use Dependency Injection (e.g Ninject) to inject the DbContext to the
Wrapper. Then you can define the lifetime of the DBContext instances. If it is a web application, then you can define the lifetime of the DbContext to be within the life of the Web Request (InRequestScope), so that it will automatically dispose of the DbContext after the Web Request ends.
You would no longer require creating the DbContext, since Ninject creates it for you and manages its disposal.
Related
I've been working on several non-web applications with Entity Framework and always it was struggling for me to find a correct approach for implementing Generic Repository with DbContext.
I've searched a lot, many of articles are about web applications which have short-living contexts. In desktop approaches I can't find suitable method.
One approach is DbContext per ViewModel but I don't agree with coupling View with Repository layers.
Another one is using using clause this way:
using(var context = new AppDbContext())
{
// ...
}
but this way we will not have Unit of Work and also can't use IoC Containers.
So what is the best practice for using DbContext in desktop applications?
A DbContext is meant to be short-lived: it represents a unit-of-work in itself. If you need long-term object state management then you can use the ObjectStateManager in Entity Framework directly.
For ensuring access to a DbContext, add an interface IDbContextFactory<TDbContext> (or just IMyDbContextFactory if you only have a single DbContext type) and inject that into your ViewModels and use a short-lived DbContext from it:
interface IDbContextFactory<TDbContext>
where TDbContext : DbContext
{
TDbContext Create();
}
// Configure:
void ConfigureServices( YourContainer container )
{
container.RegisterSingleton( IDbContextFactory<YourDbContextType1>, // etc );
container.RegisterSingleton( IDbContextFactory<YourDbContextType2>, // etc );
container.RegisterSingleton( IDbContextFactory<YourDbContextType3>, // etc );
}
// Usage:
public class LongLivedViewModel
{
private readonly IDbContextFactory<YourDbContextType3> dbFactory;
public LongLivedViewModel( IDbContextFactory<YourDbContextType3> dbFactory)
{
this.dbFactory = dbFactory ?? throw new ArgumentNullException(nameof(dbFactory));
this.DoSomethingCommand = new RelayCommand( this.DoSomethingAsync )
}
public RelayCommand DoSomethingCommand { get; }
public async RelayCommand DoSomethingAsync()
{
using( YourDbContextType3 db = this.dbFactory.Create() )
{
// do stuff
await db.SaveChangesAsync();
}
}
}
Entity Framework Core has a built in IDbContextFactory interface.
If using SQL Server, for instance, you declare the following in the ConfigureServices method (which in WPF is generally put in App.xaml.cs).
private static void ConfigureServices(IServiceCollection services)
{
services.AddDbContextFactory<MyDbContext>(
options =>
options.UseSqlServer(MyConnectionString));
}
Make sure MyDbContext exposes this constructor:
public class MyDbContext : DbContext
{
public MyDbContext(DbContextOptions<MyDbContext> options)
: base(options)
{
}
}
After that use constructor injection in the class that will be using the context (which could be either in the ViewModel layer or the Model layer, depending on your architecture):
private readonly IDbContextFactory<MyDbContext> _contextFactory;
public ModelClass(IDbContextFactory<MyDbContext> contextFactory)
{
this._contextFactory = contextFactory;
}
public void DatabaseOperationMethod()
{
using (var context = this._contextFactory.CreateDbContext())
{
// Do database stuff
}
}
I am working on a big project that 80% completed (Some features need to be implemented though).But recently we discovered that the project doesn't allow concurrent requests (I mean multiple users request to same repository). Sometime we get null referece & sometimes "Executed can not open available connection , connection state is closed" etc.
Our source code is strongly restricted outside of the world. Here is some code.Let me know if there is any architectural problem, as architectural guys left company. It's using ninject 3.0. I already used InRequestScope() for all manager's repositories but no luck
Update: I am not using any ORM here, I am trying to connect SqlServer through data adapter in my DbContext class
public class DbContext
{
//execute query , nonquery etc using adapter & datatable
//Example
var dt=new DataTable();
_adapter=new _dbfactory.CreateAdapter();
_adapter.Fill(dt);
return dt;
}
//MyController
public class MyController
{
private readonly IMyManager_iMyManager;
public MyController(IMyManager iMyManager){_iMyManager=iMyManager}
public ActionResult Save()
{
_iMyManager.Save()
}
}
// My Manager
public class MyManager:IMyManager
{
private readonly IMyRepository _iMyRepository;
DbContext _dbContext=new
DbContext("someParameter","connectionstring");
public MyManager
(
IMyRepository iMyRepository, DbContext dbContext
)
{
_iMyRepository=iMyRepository;
_dbContext=dbContext;
}
Public DataTable GetDataTable()
{
try
{
_dbContext.Open();
_iMyRepository.GetDataTable()
}
catch(Exception ex){}
finally{_dbContext.Close()}
}
}
// here is the repository
Public class MyRepository:IMyRepository
{
public _dbContext;
public MyRepository(DbContext dbContext)
{
_dbContext=dbContext;
}
public DataTable GetDataTable()
{ return _dbContext.ExecuteQuery()}
}
Finally Here is our ninject binding
public class NinjectDependencyResolver()
{
var context=new DbContext("someparameter","connectionStrin");
kernel.Bind<IMyManager>().To<MyManager>().WithConstructorArgument("_dbContext",context);
kernel.Bind<IMyRepository >().To<MyRepository >().WithConstructorArgument("_dbContext",context);
}
there can have some typo in my code as I wrote everything in so editor
I think you did this too complicated in Ninject Dependency Resolver.
You shouldn't create DbContext with a new keyword. Instead you should make Ninject to be resolving DbContext in request scope or in thread scope.
To register DbContext you can do it like this:
kernel.Bind<DbContext>().To<MyDbContext>().WithConstructorArgument("someArgument", "someValue").InRequestScope();
kernel.Bind<IMyManager>().To<MyManager>().InRequestScope();
kernel.Bind<IMyRepository>().To<MyRepository>().InRequestScope();
You don't need to precise the constructor argument to DbContext as DbContext is only once registered in the Ninject.
You can also register DbContext to a DbContextProvider class and there you can add some specific logic to resolve object.
Example:
kernel.Bind<DbContext>().ToProvider<MyDbContextProvider>().InRequestScope();
internal class MyDbContextProvider : Ninject.Activation.IProvider
{
public object Create(IContext context)
{
return new MyDbContext("connectionStringArgument";
}
public Type Type { get { return typeof (MyDbContext); } }
}
I hope this helps.
You need to remove this initialization in the MyManager since you pass the initialized DbContext via IoC.
DbContext _dbContext=new
DbContext("someParameter","connectionstring");
You also need to remove the finally block in the GetDataTable in the MyManager class since as a rule of thumb, if the object is initialized via IoC, it should be destroyed by IoC as well.
finally{_dbContext.Close()}
If you are initializing something in the field level then why would you initialize it again from the constructor?
private readonly IMyRepository _iMyRepository;
DbContext _dbContext=new DbContext("someParameter","connectionstring");
public MyManager(IMyRepository iMyRepository, DbContext dbContext)
{
_iMyRepository=iMyRepository;
_dbContext=dbContext;
}
This may also be a typo. Either remove the _dbContext initialization from the constructor or delegate the task of initialization to the caller of this class.
Multiple initialization can also be the problem. since you are doing dbcontext initialization both in NinjectDependencyResolver() and MyManager. For this you are getting two different exceptions. This is a platform design issue i guess
Two problems:
// My Manager
public class MyManager:IMyManager
{
private readonly IMyRepository _iMyRepository;
DbContext _dbContext=new
DbContext("someParameter","connectionstring");
public MyManager
(
IMyRepository iMyRepository, DbContext dbContext
)
{
_iMyRepository=iMyRepository;
_dbContext=dbContext;
}
The new that is created for the field will be overwritten when the constructor is called.
public class NinjectDependencyResolver()
{
var context=new DbContext("someparameter","connectionStrin");
kernel.Bind<IMyManager>().To<MyManager>().WithConstructorArgument("_dbContext",context);
kernel.Bind<IMyRepository >().To<MyRepository >().WithConstructorArgument("_dbContext",context);
}
You create the context here once and pass it to each object creation. So you are still reusing the context object instead of creating it for each request scope.
I want to access some data within my overriden SaveChanges() in my dbcontext without passing any parameters. Any suggestions? I'm working with MVC4 and Entity Framework Database-First.
public partial class Entities : DbContext
{
public override int SaveChanges()
{
// i want to get user info from MVC model but no need to pass any parameters when call SaveChanges()
var UserInfo = userInfo;
// Call the original SaveChanges(), which will save both the changes made and the audit records
return base.SaveChanges();
}
}
Solution 1: Dependency Injection
This solution is pretty extensible, but you would have to modify the code in your repositories and controllers to use the injected dependencies instead of creating new instances with new.
Install Ninject. In Visual Studio, find the Package Manager Console and run Install-Package Ninject.MVC4 -dependencyVersion Highest in there.
Add constructor injection. Modify your controller, so that it gets an instance of your repository in its constructor. Modify your repository, so that it gets an instance of your entity context in its constructor. Cache your dependencies in private fields. Example code:
// In your controller:
public MyController(MyRepository repo)
{
this.repo = repo;
}
// In your repository:
public MyRepository(Entities context)
{
this.context = context;
}
// In your entities:
public Entities(UserInfo userInfo)
{
this.userInfo = userInfo;
}
Add a UserInfo provider. We need to tell Ninject where to get the UserInfo from. We can use the provider interface here:
public class UserInfoProvider : Provider<UserInfo>
{
protected override UserInfo CreateInstance(IContext context)
{
UserInfo UserInfo = new UserInfo();
// Do some complex initialization here.
return userInfo;
}
}
Add bindings. We need to tell Ninject to use the provider. We also want the lifetime of a UserInfo instance and of our entity context to be bound to the request cycle of MVC. Update your App_Start\NinjectWebCommon.cs:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<Entities>()
.ToSelf()
.InRequestScope();
kernel.Bind<UserInfo>()
.ToProvider<UserInfoProvider>()
.InRequestScope();
}
Run your app. Ninject should use your constructors and provide the requested dependencies.
For further information, visit the Ninject Wiki.
Solution 2: Thread local context
This requires no modification to your repositories, but it makes the code less testable and resembles an anti pattern somehow. This won't work if your controller calls multithreaded code.
Add context class.
public class UserInfoContext : IDisposable
{
private static readonly ThreadLocal<UserInfo> UserInfos = new ThreadLocal<UserInfo>();
public static UserInfo Current
{
get
{
if (UserInfos == null)
{
throw new InvalidOperationException("UserInfoContext has not been set.");
}
return UserInfos.Value;
}
}
public static UserInfoContext Create(UserInfo userInfo)
{
if (userInfo == null)
{
throw new ArgumentNullException("userInfo");
}
if (UserInfos.Value != null)
{
throw new InvalidOperationException("UserInfoContext should not be nested.");
}
UserInfos.Value = userInfo;
return new UserInfoContext();
}
private UserInfoContext() { }
public void Dispose()
{
UserInfos.Value = null;
}
}
Wrap your controller code. Example:
public ActionResult Index()
{
using (UserInfoContext.Create(myUserInfo))
{
// do stuff that calls your repositories
return View();
}
}
Update your Entities class.
public partial class Entities : DbContext
{
public override int SaveChanges()
{
var UserInfo = UserInfoContext.Current;
// Call the original SaveChanges(), which will save both the changes made and the audit records
return base.SaveChanges();
}
}
I have a simple repository that fetches some data using EF6. I'm also using a DI framework to inject the dependencies.
namespace Domain
{
public interface IMyRespository
{
List<MyObject> FetchObjects();
}
}
namespace Data
{
public class MyRepository : IMyRepository
{
private readonly MyDbContext _context;
public MyRepository(MyDbContext context)
{
_context = context;
}
public List<MyObjects> FetchObjects()
{
return _context.MyObjects.ToList();
}
}
}
A new requirement states that I need to log each FetchObjects() call and it's outputs. I thought this would be perfect example to apply the Decorator pattern.
namespace Domain
{
public class MyRepositoryDecorator : IMyRepository
{
private readonly IMyRepository _inner;
private readonly ILogRepository _logRepository;
public MyRepositoryDecorator(IMyRepository inner, ILogRepository logRepository)
{
_inner = inner;
_logRepository = logRepository;
}
public List<MyObjects> FetchObjects()
{
var objects = _inner.FetchObjects();
var logObject = new LogObject(objects);
_logRepository.Insert(logObject);
_logRepository.Save();
return objects;
}
}
}
Now I'm looking to employ the UnitOfWork pattern and I'm unsure how to implement in this case.
As I understand it some component needs to manage the UnitOfWork. So in this case a service class would make some calls and at the end call Save/Commit on the UnitOfWork class.
However if the repository interface indicates a readonly action there is no reason for the service class to wrap the call in a UnitOfWork and call Save/Commit at the end. It would look really weird too. However the decorator requires this to do it's job.
I'm probably missing some essential construct here. Any ideas on how to properly approach this scenario?
It would be a bad idea to mix UoW with Repository using Decorator (or similar) simply because it is not unusual for UoW to span across multiple repositories.
Also it is not up to the Repository to decide whether UoW should be committed or not. Repositories should know as less as possible about UoWs, ideally (and it is the case most of the time) nothing.
In your scenario the UnitOfWork class would pretty much only handles the transaction, so it can be implemented as a simple wrapper around TransactionScope, something like:
public sealed class UnitOfWork : IDisposable {
private readonly TransactionScope _transaction;
public UnitOfWork() { _transaction = new TransactionScope(); }
public void Commit { _transaction.Commit(); }
public void Dispose { _transaction.Dispose(); }
}
Now it is up to the service to instantiate/commit UoW, not up to Repository:
//assuming in a service
public void DoSomething() {
using(var uow = new UnitOfWork()) {
_repositoryA.UpdateSomething();
_repositoryB.DeleteSomething();
_uow.Commit();
}
}
And if your service only wants to read the data, then just do not use UnitOfWork in that operation (or use it without calling Commit so it will just be disposed).
In case if your repository needs to know about UoW, it will normally be passed as another parameter in its behavior method.
Note that it is not done because Repository wants to call Commit, but sometimes (rarely) it is needed for the repository to "enlist" to UoW. These cases are rather more complex.
I currently been assigned to a asp mvc project using entity framework. This will be a Line of Business application. I want to develop this app using repository and unit of work pattern. I'm new to this pattern (and new to .net too) and i am having a problem in understanding the pattern and how to implement it.
I have read numerous articles and i think this is how my application should be
Entity Framework -> Repository -> Unit of Work -> Client (Asp MVC)
I attach some code from this article
http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
using System;
using ContosoUniversity.Models;
namespace ContosoUniversity.DAL
{
public class UnitOfWork : IDisposable
{
private SchoolContext context = new SchoolContext();
private GenericRepository<Department> departmentRepository;
private GenericRepository<Course> courseRepository;
public GenericRepository<Department> DepartmentRepository
{
get
{
if (this.departmentRepository == null)
{
this.departmentRepository = new GenericRepository<Department>(context);
}
return departmentRepository;
}
}
public GenericRepository<Course> CourseRepository
{
get
{
if (this.courseRepository == null)
{
this.courseRepository = new GenericRepository<Course>(context);
}
return courseRepository;
}
}
public void Save()
{
context.SaveChanges();
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
context.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}
Unit of Work will have repositories and will create DBContext upon creation
So controller will create Unit of Work upon creation.
To Show data i will use this code
var department = UoW.departmentRepository.Find(1);
return View(department);
and when client click save button, i will run this code
UoW.departmentRepository.Update(department);
UoW.Save();
My question:
What if it takes hours from data retrieval until the client click save button. From what i know, we have to keep context as short as possible.
Where should i put business logic? Do i put it in repository? So i would call UoW.departmentRepository.Validate(department) before save. But then, what if i need to validate entity which relate to other entity. Do i call UoW.departmentRepository.Validate(course, department)?
Is there a complete sample project for this kind of application?
EDIT
As Ant P adviced, i need to add another layer to put my business logic.
This is what i have come so far
Unit Of Work:
public class UnitOfWork : IDisposable
{
private DBContext _context = new DBContext();
public DBContext Context
{
get
{
return this._context;
}
}
public void Save()
{
_context.SaveChanges();
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
context.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
Business Logic:
public class SalesBusinessLogic : IDisposable
{
private ICustomerRepository _customerRepo;
private ISalesRepository _salesRepo;
private UnitOfWork _uow;
public SalesBusinessLogic(UnitOfWork uow)
{
this._uow = uow;
}
public ICustomerRepository CustomerRepo
{
get
{
if (this._customerRepo == null)
{
this._customerRepo = new CustomerRepository(this._uow);
}
return this._customerRepo;
}
}
public ISalesRepository SalesRepo
{
get
{
if (this._salesRepo == null)
{
this._salesRepo = new SalesRepository(this._uow);
}
return this._salesRepo;
}
}
public bool Validate(Sales sales)
{
//this is where validation performed
return true;
}
}
Controller:
public SalesController : Controller
{
private UnitOfWork _uow = new UnitOfWork();
private SalesBusinessLogic _bl = new SalesBusinessLogic(this._uow);
public ActionResult Index()
{
var sales = _bl.SalesRepo.Find(1);
sales.CustomerID = 1;
if _bl.Validate(sales)
{
_bl.SalesRepo.Update(sales);
_uow.Save();
}
return View(sales);
}
}
Here UnitOfWork act only as provider of dbcontext, which will be consumed by business logic and repository.
Repository will be in BusinessLogic class.
Server side validation will be handled by BusinessLogic and client side validation will be handled by viewmodel in Web Layer.
My only concern is that dbcontext in UnitofWork is publicly accessible.
Am i in the right direction here?
What if it takes hours from data retrieval until the client click save button. From what i know, we have to keep context as short as possible.
This isn't an issue - the controller is instantiated per request. It doesn't persist while the user views the page. It sounds like you're misunderstanding at what point the controller is instantiated. When you instantiate the UnitOfWork within the controller's constructor, the process flow goes like this:
The user issues a POST request (by clicking 'Save').
The request reaches the server and the controller is instantiated (thereby instantiating the unit of work).
The action method is called.
The unit of work is disposed.
Where should i put business logic? Do i put it in repository? So i would call UoW.departmentRepository.Validate(department) before save. But then, what if i need to validate entity which relate to other entity. Do i call UoW.departmentRepository.Validate(course, department)?
Typically, your business logic would be abstracted into a separate layer that sits between your web application and your repositories. Tutorials that show you repositories injected directly into controllers assume that you have "thin" business logic.
However, validation definitely isn't the job of a repository. You should create a separate view model for each view and validate those in your controller. The repository should be used pretty much solely for CRUD operations.