How i can inject context from UnitOfWork using StructureMap - c#

Hi i have mi project in MVC5, i am using Identity 2.0, commonRepository and Structuremap to inject dependencies, the problem is when I am in the controller AccountController, i have one Contex and when my UnitOfWork inject the repositories it create other Instance.
how I can inject or replace the context of the identity whit my context from my UnitOfWork.
Regards
Update
AccountController
public class AccountController : Controller
{
private readonly ApplicationSignInManager SignInManager;
private readonly ApplicationUserManager UserManager;
private readonly IAuthenticationManager AuthenticationManager;
// private readonly IUbicationDao _ubicationDao;
private readonly ICultureDao _cultureDao;
private readonly ICurrencyDao _currecieDao;
public AccountController(ApplicationUserManager userManager, ApplicationSignInManager signInManager, ICultureDao cultureDao, ICurrencyDao currecieDao, IAuthenticationManager authenticationManager)
{
UserManager = userManager;
SignInManager = signInManager;
// _ubicationDao = ubicationDao;
_cultureDao = cultureDao;
_currecieDao = currecieDao;
AuthenticationManager = authenticationManager;
}}
DefaultRegistry StructureMap
public class DefaultRegistry : Registry {
#region Constructors and Destructors
public static IList<string> Assemblies
{
get
{
return new List<string>
{
"Interfaz",
"Persistencia"
};
}
}
public static IList<Tuple<string, string>> ManuallyWired
{
get
{
return new List<Tuple<string, string>>()
{
Tuple.Create("IUserStore<ApplicationUser>", "UserStore<ApplicationUser>>"),
Tuple.Create("DbContext", "ApplicationDbContext"),
Tuple.Create("IAuthenticationManager", "HttpContext.Current.GetOwinContext().Authentication"),
};
}
}
public DefaultRegistry()
{
Scan(
scan =>
{
foreach (var assembly in Assemblies)
{
scan.Assembly(assembly);
}
scan.TheCallingAssembly();
scan.WithDefaultConventions();
scan.With(new ControllerConvention());
});
For<IUserStore<ApplicationUser>>().Use<UserStore<ApplicationUser>>();
For<DbContext>().Use<ApplicationDbContext>(new ApplicationDbContext());
For<IAuthenticationManager>().Use(() => HttpContext.Current.GetOwinContext().Authentication);
//DAos
For<ICultureDao>().Use<CultureDao>();
For<ICurrencyDao>().Use<CurrencyDao>();
For<IUbicationDao>().Use<UbicationDao>();
For<IActivatorWrapper>().Use<ActivatorWrapper>();
For<IUnitOfWorkHelper>().Use<UnitOfWorkHelper>();
}
#endregion
}
UnitofWork
public class UnitOfWorkHelper : IUnitOfWorkHelper
{
private ApplicationDbContext _sessionContext;
public event EventHandler<ObjectCreatedEventArgs> ObjectCreated;
public IApplicationDbContext DBContext
{
get
{
if (_sessionContext == null)
{
_sessionContext = new ApplicationDbContext();
((IObjectContextAdapter)_sessionContext).ObjectContext.ObjectMaterialized += (sender, e) => OnObjectCreated(e.Entity);
}
return _sessionContext;
}
}
private void OnObjectCreated(object entity)
{
if (ObjectCreated != null)
ObjectCreated(this, new ObjectCreatedEventArgs(entity));
}
public void SaveChanges()
{
this.DBContext.SaveChanges();
}
public void RollBack()
{
if (_sessionContext != null)
_sessionContext.ChangeTracker.Entries()
.ToList()
.ForEach(entry => entry.State = EntityState.Unchanged);
}
public void Dispose()
{
if (_sessionContext != null)
_sessionContext.Dispose();
}
}

after a lot analyzing and understand, I finally find the solution,
first i have to inject the same context to avoid inject a new instance of the Context. the solution is:
For<DbContext>().Use(()=>System.Web.HttpContext.Current.GetOwinContext().Get<ApplicationDbContext>());
before i was injecting and add a new instance of the DBContex.
For<DbContext>().Use<ApplicationDbContext>(new ApplicationDbContext());

Related

How to set up .net core service that uses a generic repository

I am building a generic data repository using .netcore 3.0. with EF Core. How can I set up the service where I don't have to provide the actual entity name such as this:
services.AddScoped<RepositoryBase<Feature>>();
Is there a way to configure options that will all me to do this?
These are mostly CRUD operations.
The Generic repository base
namespace CoreAPI1.Data.Services
{
public class RepositoryBase<TEntity> where TEntity : class
{
private readonly DbContext _context;
private readonly DbSet<TEntity> _dbSet;
public RepositoryBase(DbContext context)
{
_context = context;
if (_context == null)
throw new ArgumentNullException();
_dbSet = context.Set<TEntity>();
}
public async Task<IEnumerable<TEntity>> GetAll()
{
return _dbSet.AsNoTracking().ToList();
}
}
}
The services
public static void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<TruckContext>(ServiceLifetime.Scoped);
services.AddScoped<IFileService, FileService>();
services.AddScoped<IImageRepository, ImageRepository>();
services.AddScoped<RepositoryBase<Feature>>();
services.AddControllers();
// services.AddAutoMapper(typeof(Truck));
services.AddMvc(_x=>_x.EnableEndpointRouting =
false).SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
}
The calling controller
namespace CoreAPI1.Data.Controllers
{
[Route("api/features")]
[ApiController]
public class FeaturesController :ControllerBase
{
private RepositoryBase<Data.Entities.Feature> _repository;
private IMapper _mapper;
public FeaturesController(RepositoryBase<Data.Entities.Feature> repository, IMapper mapper)
{
_repository = repository ?? throw new ArgumentNullException(nameof(_repository));
_mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
}
[HttpGet]
public async Task<IEnumerable<Domain.Models.Feature>> GetFeatures()
{
var _features = await _repository.GetAllAsync();
List<Domain.Models.Feature> _returnedFeatures = new List<Domain.Models.Feature>();
try
{
foreach (var f in _features)
{
var _returnedFeature = _mapper.Map<Domain.Models.Feature>(f);
_returnedFeatures.Add(_returnedFeature);
}
return _returnedFeatures;
}
catch (Exception ex)
{
throw new Exception(ex.ToString());
}
}
}
}
You can register the type generically, if that's what you're talking about:
services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
That would then inject Repository<Foo> for IRespository<Foo>, for example.
Implement Unit of Work class that wraps DbContext and creates repository.

How to dispose the object created by Unity DI right after the completing the request?

I want to know if there is a better to way to handle this.
I've set up Unity for dependency injection for our project. The project itself is an ASP.NET application that uses Web API.
I have the following packages installed.
Unity
Unity.ASPNet.WebAPI
I see no option to close/dispose the DBContext right after fetching the data.
My controller
public class NinjasController : ApiController
{
public Ninja Get(int id)
{
INinjaRepository repository = UnityConfig.Container.Resolve(typeof(INinjaRepository), null) as INinjaRepository;
Ninja ninja = repository.GetNinjaById(id);
repository.CanBeDisposed = true;
repository = null;
UnityConfig.PerRequestLifetimeManager.Dispose();
return ninja;
}
}
UnityConfig
public static class UnityConfig
{
private static Lazy<IUnityContainer> container =
new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
public static IUnityContainer Container => container.Value;
public static PerRequestLifetimeManager PerRequestLifetimeManager;
public static void RegisterTypes(IUnityContainer container)
{
PerRequestLifetimeManager = new PerRequestLifetimeManager();
container.RegisterType<INinjaRepository, NinjaRepository>(PerRequestLifetimeManager);
}
}
Lifetime Manager
public class PerRequestLifetimeManager : TransientLifetimeManager, IDisposable
{
private static List<IBaseRepository> list = new List<IBaseRepository>();
public override void SetValue(object newValue, ILifetimeContainer container = null)
{
base.SetValue(newValue, container);
IBaseRepository disposable = newValue as IBaseRepository;
if (disposable != null)
list.Add(disposable);
}
public void Dispose()
{
foreach (IBaseRepository item in list.FindAll(item => item.CanBeDisposed))
{
if (item != null)
{
try
{
item.Dispose();
}
catch (Exception)
{
// log exception and continue
}
}
}
list.RemoveAll(item => item.CanBeDisposed);
}
}
Repository
public class GenericRepository<TEntity> : IGenericRepository<TEntity> where TEntity : class
{
internal DbContext _context;
internal DbSet<TEntity> _dbSet;
public bool CanBeDisposed { get; set; }
public GenericRepository(DbContext context)
{
_context = context;
_dbSet = context.Set<TEntity>();
}
protected void Dispose(bool disposing)
{
if (disposing)
{
if (_context != null)
{
_context.Dispose();
_context = null;
}
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
First you might want to add one more Unity bootstrapper to your project Unity.AspNet.Mvc
https://msdn.microsoft.com/en-us/library/dn507440(v=pandp.30).aspx
To use the PerRequestLifetimeManager class in an ASP.NET Web API application, you must also add the the Unity bootstrapper for ASP.NET MVC NuGet package to your project.
Unity.Mvc and Unity.AspNet.WebApi will register your controllers for DI.
UnityConfig.cs
public static void RegisterTypes(IUnityContainer container)
{
container.RegisterType<INinjaContext, NinjaContext>(new PerRequestLifetimeManager());
container.RegisterType<INinjaRepository, NinjaRepository>(new PerRequestLifetimeManager());
}
UnityWebApiActivator.cs Uncomment the line...
public static void Start()
{
// Use UnityHierarchicalDependencyResolver if you want to use
// a new child container for each IHttpController resolution.
var resolver = new UnityHierarchicalDependencyResolver(UnityConfig.Container);
...
}
UnityMvcActivator.cs Uncomment the line...
public static void Start()
{
...
// TODO: Uncomment if you want to use PerRequestLifetimeManager
Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
}
Your controller is simply
public class NinjasController : ApiController
{
private readonly INinjaRepository repository;
public NinjasController(INinjaRepository repository)
{
this.repository = repository;
}
public Ninja Get(int id)
{
var ninja = repository.GetNinjaById(id);
return ninja;
}
}
With PerRequestLifetimeManager Unity will take care of disposal after the request is complete.
I have an example here https://github.com/jasenhk/MovieStar
If you are using OWIN see Unity IoC does not inject dependency into Web API Controller

EF 7 (Core). Create DBContext like AddTransient

According to documents when I configure DbContext like below DI register it in scope (per http request)
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<DBData>(options => {
options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]);
}
);
The problem appears when I am trying to access it in another thread.
public class HomeController : Controller
{
private readonly DBData _context;
public HomeController(DBData context)
{
_context = context;
}
public IActionResult StartInBackground()
{
Task.Run(() =>
{
Thread.Sleep(3000);
//System.ObjectDisposedException here
var res = _context.Users.FirstOrDefault(x => x.Id == 1);
});
return View();
}
}
I want to configure DbContext creation per each call (AddTransition). It would give me possibility to write next code
public void ConfigureServices(IServiceCollection services)
{
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<DBData>(options => {
//somehow configure it to use AddTransient
options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]);
}
);
services.AddTransient<IUnitOfWorkFactoryPerCall, UnitOfWorkFactory>();
services.AddScoped<IUnitOfWorkFactoryPerRequest, UnitOfWorkFactory>();
services.AddMvc();
}
public interface IUnitOfWorkFactoryPerCall : IUnitOfWorkFactory { }
public interface IUnitOfWorkFactoryPerRequest : IUnitOfWorkFactory { }
public interface IUnitOfWorkFactory : IDisposable
{
DBData Context { get; }
}
public class UnitOfWorkFactory : IUnitOfWorkFactoryPerCall, IUnitOfWorkFactoryPerRequest
{
public UnitOfWorkFactory(DBData context)
{
Context = context;
}
public DBData Context
{
get; private set;
}
public void Dispose()
{
Context.Dispose();
}
}
So now if I want to create DBContext per request I will use IUnitOfWorkFactoryPerRequest, and when I want to use DBContext in some background thread I can use IUnitOfWorkFactoryPerCall.
My temporary solution.
I created singleton which can create Context "in transient way"
public class AppDependencyResolver
{
private static AppDependencyResolver _resolver;
public static AppDependencyResolver Current
{
get
{
if (_resolver == null)
throw new Exception("AppDependencyResolver not initialized. You should initialize it in Startup class");
return _resolver;
}
}
public static void Init(IServiceProvider services)
{
_resolver = new AppDependencyResolver(services);
}
private readonly IServiceProvider _serviceProvider;
public AppDependencyResolver(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public IUnitOfWorkFactory CreateUoWinCurrentThread()
{
var scopeResolver = _serviceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope();
return new UnitOfWorkFactory(scopeResolver.ServiceProvider.GetRequiredService<DBData>(), scopeResolver);
}
}
Then I call init method in Startup Configure method
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
AppDependencyResolver.Init(app.ApplicationServices);
//other configure code
}
And after all I can call AppDependencyResolver.Current.CreateUoWinCurrentThread() in some background thread.
If someone can provide more elegant solution I will be appreciated.
Within your controller, why are you trying to inject into private readonly DBData _context;? If you've registered your IUnitOfWorkFactoryPerCall via DI, you should be injecting that into your controller I believe? You then access your context via the interface.
To expand, this is what I am suggesting you do:
public class HomeController : Controller
{
private readonly IUnitOfWorkFactoryPerCall _contextFactory;
public HomeController(IUnitOfWorkFactoryPerCall contextFactory)
{
_contextFactory = contextFactory;
}
public IActionResult StartInBackground()
{
Task.Run(() =>
{
Thread.Sleep(3000);
//System.ObjectDisposedException here
var res = _contextFactory.Context.Users.FirstOrDefault(x => x.Id == 1);
});
return View();
}
}

Call different methods, from different repositories, in same transaction using Unit of work

I am still learning UnitOfWork pattern and I am not comfortable with this yet. I found many examples but nothing is clear enough for my problem.
I want use UnitOfWork with Ado.Net.
I have many repositories. I want call different methods from different repositories in same transaction using Unit of work.
For example a have this 2 repositories.
public class FirstRepository : IFirstRepository
{
private readonly ILogger logger;
private readonly IImportConfiguration configuration;
public FirstRepository(ILogger logger, IImportConfiguration configuration)
{
this.logger = logger;
this.configuration = configuration;
}
public int Save()
{
//Save to DB with Ado.Net
return 1;
}
}
public class SecondRepository : ISecondRepository
{
private readonly ILogger logger;
private readonly IImportConfiguration configuration;
public SecondRepository(ILogger logger, IImportConfiguration configuration)
{
this.logger = logger;
this.configuration = configuration;
}
public int Update()
{
//Update in DB with Ado.Net
return 1;
}
}
I want call functions Save() and Update() in same transaction.
using (var uow = UnitOfWorkFactory.Create())
{
firstRepository.Save();
secondRepository.Update();
_unitOfWork.SaveChanges();
}
Problem is how to use same UnitOfWork in both repositories ? Only thing I can see is add additional parameter to functions
//in first repository
Save(IUnitOfWork uow)
//in second repository
Update(IUnitOfWork uow)
//****************************
using (var uow = UnitOfWorkFactory.Create())
{
firstRepository.Save(uow);
secondRepository.Update(uow);
_unitOfWork.SaveChanges();
}
This is ugly solution, because i must have this parameter in all functions that work with DB.
I am using Dependency injection. ILogger and IImportConfiguration are injected with AutoFac. Maybe would be good to register all repositories in UnitOfWork? But how to do that? I cant have just one instance injected in all repositories.
Any idea?
public class UnitOfWork
{
public DbSet<Company> Companies { get; set; }
public int SaveChanges()
{
underlyingContext.SaveChanges();
}
}
public class UnitOfWorkFactory
{
public UnitOfWork Create()
{
// real creation logic
return new UnitOfWork();
}
}
public class CompanyRepository
{
private readonly UnitOfWork uow;
public CompanyRepository(UnitOfWork uow)
{
uow = uow;
}
public void Add(Company company)
{
uow.Companies.Add(company);
}
}
public class CompanyRepositoryFactory
{
public Create(UnitOfWork uow)
{
new CompanyRepository(uow);
}
}
Tying it all together:
var uow = new UnitOfWorkFactory().Create();
var companyRepository = new CompanyRepositoryFactory().Create(uow);
So to use DI, you need to create interfaces for all these.
The unit of work is based round some Data Layer connection, for example EF uses DbContext which you would use in the underlying UnitOfWork class.
Other things you can do is make IUnitOfWork (the interface) inherit IDisposable so you use the using().
To make it so you don't have a hundred repository classes (although not really a bad thing) you can make it Generic, so IRepository<T> and Repository<T>
So for a generic repo and unit of work using EF.
public class UnitOfWork : IUnitOfWork
{
ProjectDbContext context;
public UnitOfWork() {
context = new ProjectDbContext();
}
public IQueryable<T> Query<T>(Expression<Func<bool, t>> predicate)
{
return context.Set<T>().Where(predicate);
}
public void Add<T>(T entity)
{
context.Set<T>().Add(entity);
}
public int SaveChanges()
{
return context.SaveChanges();
}
public void Dispose()
{
context.Dispose();
}
}
public class UnitOfWorkFactory
{
Lazy<UnitOfWork> lazyUOW = new Lazy<UnitOfWork>(() => new UnitOfWork());
public UnitOfWork Create()
{
// having the DI initialise as Singleton isn't enough.
return lazyUOW.Value;
}
}
public class Repository<T> : IRepository<T>
{
private readonly IUnitOfWork uow;
public Repository(IUnitOfWork uow)
{
uow = uow;
}
public void Add(T entity)
{
uow.Add(entity);
}
public List<T> AllBySomePredicate(Expression<Func<bool, T>> predicate)
{
return uow.Query(predicate).ToList();
}
}
public class RepositoryFactory : IRepositoryFactory
{
public Create<T>(UnitOfWork uow)
{
new Repistory<T>(uow);
}
}
Usage:
public class CompanyController : Controller
{
private readonly IUnitOfWorkFactory uowFactory;
private readonly IRepositoryFactory repoFactory;
public CompanyController (
IUnitOfWorkFactory uowFactory,
IRepositoryFactory repoFactory)
{
uowFactory = uowFactory;
repoFactory = repoFactory;
}
public ActionResult Index()
{
using(var uow = uowFactory.Create())
{
var companyRepo = repoFactory.Create<Company>(uow);
return View(companyRepo.AllBySomePredicate(x => x.CompanyJoined == DateTime.Now.AddMonths(-2)));
}
}
}

Injecting IUnitOfWork into IRepository constructor

I am trying to use the Unity IoC with the unit of work & repository patterns, however I'm struggling to work out how my repository would get it's Nhibernate session to perform it's work...
Below I have my IUnityContainer which does my IoC bindings.. I then have my NHibernate repo which needs to be provided with a ISession, which should be provided from the NHibernate unit of work, but I am now sure how I can tell Unity to provide it in it's constructor..
I have made a binding for the IUnitOfWork to a Nhib... one, but how does one pass that value in the IRepository RegisterType?
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
NHibernateHelper helper = new NHibernateHelper();
// register all your components with the container here
// e.g. container.RegisterType<ITestService, TestService>();
container.RegisterControllers();
container.RegisterType<IUnitOfWork, NHibernateUnitOfWork>(new HierarchicalLifetimeManager());
container.RegisterInstance<ISessionFactory>(helper.SessionFactory);
container.RegisterType<IRepository, NHibernateRepository>() ;
return container;
}
public class NHibernateRepository : IRepository
{
public NHibernateRepository(ISession session)
{
_session = session;
}
}
public class NHibernateUnitOfWork : IUnitOfWork
{
private readonly ISessionFactory _sessionFactory;
private readonly ITransaction _transaction;
public ISession Session { get; private set; }
public NHibernateUnitOfWork(ISessionFactory sessionFactory)
{
_sessionFactory = sessionFactory;
Session = _sessionFactory.OpenSession();
Session.FlushMode = FlushMode.Auto;
_transaction = Session.BeginTransaction(IsolationLevel.ReadCommitted);
}
}
Register your ISession with your IUnityContainer like so:
container.RegisterType<ISession>(new InjectionFactory(c => c.Resolve<ISessionFactory>().OpenSession());
Then when an ISession is required, an ISessionFactory will be resolved and a session started.
In the applications I work on, we define our repositories and unit of work like so:
public class NhUnitOfWork : IUnitOfWork
{
readonly ISession _session;
public IRepository<T> GetRepository<T>() where T : class
{
return new NhRepository<T>(_session);
}
public NhUnitOfWork(ISession session)
{
_session = session;
}
public void Dispose()
{
// Dispose logic, i.e. save/rollback
}
}
public class NhRepository<T> : IRepository<T> where T : class
{
readonly ISession _session;
public void Add(T item)
{
_session.Save(item);
}
public void Delete(T item)
{
_session.Delete(item);
}
public void Update(T item)
{
_session.Update(item);
}
public NhRepository(ISession session)
{
_session = session;
}
}
Then your services use it something like this:
public class MyService
{
readonly Func<IUnitOfWork> _unitOfWorkFactory;
public MyService(Func<IUnitOfWork> unitOfWorkFactory)
{
_unitOfWorkFactory = unitOfWorkFactory;
}
public void DoServiceStuff()
{
using(var uow = _unitOfWorkFactory())
{
var newUser = new User() { Username = "My User" };
var userRepo = uow.GetRepository<User>();
userRepo.Add(newUser);
uow.Save();
}
}
}
You want to create instance of "IRepository", you need to initialize mapping for all it dependencies. It's single: "ISession"

Categories

Resources