I have an asp.net process which also consumes messages from a servicebus (MassTransit). For webrequests my database session is resolved with a PerWebRequest lifestyle.
But when the process consumes a message from MassTransit I need the database session to have another lifestyle, as no HttpContext is available.
I have made this:
public class PerRequestLifeStyleManager : ILifestyleManager
{
readonly PerWebRequestLifestyleManager perWebRequestLifestyleManager;
readonly PerThreadLifestyleManager perThreadLifestyleManager;
public PerRequestLifeStyleManager()
{
perWebRequestLifestyleManager = new PerWebRequestLifestyleManager();
perThreadLifestyleManager = new PerThreadLifestyleManager();
}
public void Init(IComponentActivator componentActivator, IKernel kernel, ComponentModel model)
{
perWebRequestLifestyleManager.Init(componentActivator, kernel, model);
perThreadLifestyleManager.Init(componentActivator, kernel, model);
}
public object Resolve(CreationContext context)
{
return GetManager().Resolve(context);
}
public bool Release(object instance)
{
return GetManager().Release(instance);
}
public void Dispose()
{
GetManager().Dispose();
}
ILifestyleManager GetManager()
{
if (HttpContext.Current != null)
{
return perWebRequestLifestyleManager;
}
return perThreadLifestyleManager;
}
}
Can anyone tell me, if this is the right way to go? And if it isn't, what is?
Thanks.
EDIT: I have just updated the question with some code that seems to work (before it was untested). I still am eager to know if this - seen from a Windsor perspective - is safe and sound.
Try using one of the hybrid lifestyles.
By using the Castle Windsor extension, you should just be able to have your ISession as a dependency on the constructor of the consumer class. That way, the container will manage the lifecycle of the ISession, and dispose of it once the consumer is disposed by MT.
If you need even more control, you can look at how the WindsorConsumerFactory is implemented to wrap the resolution and release of the consumer class instance around the delivery of the message to the consumer.
If you need to inject something beyond that, you can also use an interceptor:
Unit of work when using MassTransit
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I am developing a new WebApi using .NetCore2.2, Autofac4, Dapper. There are few very basic questions because this is my first WebApi project. As part of this project I have to write both unit-test and integration-test.
My questions are as follows (Sample Code is give below):
What is recommended return type between "Task< IActionResult >" and "Task< IEnumerable >"?
Recommended object Scope of the dependencies in startup class for my project?
Do I really need UnitOfWork for this given project structure?
What are the flaws if I follow this design?
Is there any better way to design this API?
As TDD do I need write test cases for API layer(Controller) and Infrastructure layer only or Doman Layer (it doesn't have any logic) as well?
What are the scenario I must include in my controller unit test?
Domain Layer:
[Table("Movie")]
public class Movie
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID {get;set;}
public string Title {get;set;}
}
public interface ICommandRepository<T> where T : class
{
Task CreateAsync(T entity);
Task UpdateAsync(T entity);
Task DeleteAsync(T entity);
}
public interface IQueryRepository<T> where T : class
{
Task<IEnumerable<T>> GetAllMoviesAsync();
Task<IEnumerable<T>> GetMoviesByTitleAsync(string title);
Task<T> GetMovieByIDAsync(int id);
}
Infrastructure Layer:
public class MovieCommandContext : DbContext
{
public MovieCommandContext(DbContextOptions<MovieCommandContext> options)
: base(options)
{}
public DbSet<Movie> Movies { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
public class MovieQueryContext : IDisposable
{
private readonly IDbConnection connection;
public MovieQueryContext(string connectionString)
{
connection = new SqlConnection(connectionString);
}
public async Task<IEnumerable<Movie>> GetAllMovies()
{
// Use Dapper->QueryAsync
throw new NotImplementedException();
}
...
public void Dispose()
{
if (connection?.State == ConnectionState.Open)
connection.Close();
}
}
public class MovieCommandRepository : ICommandRepository<Movie>
{
private readonly MovieCommandContext context;
public MovieCommandRepository(MovieCommandContext dbContext)
{
context = dbContext;
}
public async Task CreateAsync(Movie movie)
{
await context.AddAsync<Movie>(movie);
await context.SaveChangesAsync();
}
public async Task UpdateAsync(Movie movie)
{
var entity = context.Attach<Movie>(movie);
context.Entry<Movie>(movie).State = EntityState.Modified;
await context.SaveChangesAsync();
}
public async Task DeleteAsync(Movie movie)
{
context.Remove<Movie>(movie);
await context.SaveChangesAsync();
}
}
public class MovieQueryRepository : IQueryRepository<Movie>
{
private readonly MovieQueryContext context;
public MovieQueryRepository(MovieQueryContext dbContext)
{
context = dbContext;
}
public async Task<IEnumerable<Movie>> GetAllMoviesAsync()
{
return await context.GetAllMovies();
}
public async Task<IEnumerable<Movie>> GetMoviesByTitleAsync(string title)
{
return await context.GetMovieByName(title);
}
public async Task<Movie> GetMovieByIDAsync(int id)
{
return await context.GetMovieByID(id);
}
}
API Layer:
[Route("api/sample")]
[ApiController]
public class SampleController : ControllerBase
{
private readonly ICommandRepository<Movie> movieCommand;
private readonly IQueryRepository<Movie> movieQuery;
public SampleController(ICommandRepository<Movie> command, IQueryRepository<Movie> query)
{
movieCommand = command;
movieQuery = query;
}
[HttpGet]
public async Task<IActionResult> GetMoviesAsync()
{
try
{
var movies = await movieQuery.GetAllMoviesAsync();
return Ok(movies);
}
catch
{
// TODO: Logging
return BadRequest();
}
}
[Route("{name:alpha}")]
[HttpGet]
public async Task<IActionResult> GetMoviesByTitle(string movieTitle)
{
try
{
var movies = await movieQuery.GetMoviesByTitleAsync(movieTitle);
return Ok(movies);
}
catch
{
// TODO: Logging
return BadRequest();
}
}
[Route("{movieID:int:min(1)}")]
[HttpGet]
public async Task<IActionResult> GetMovieByID(int movieID)
{
try
{
var movie = await movieQuery.GetMovieByIDAsync(movieID);
return Ok(movie);
}
catch
{
// TODO: Logging
return BadRequest();
}
}
[Route("")]
[HttpDelete("{id:int:min(1)}")]
public async Task<IActionResult> Delete(int id)
{
try
{
var movie = await movieQuery.GetMovieByIDAsync(id);
if (movie == null)
return BadRequest();
await movieCommand.DeleteAsync(movie);
return Ok();
}
catch
{
// TODO: Logging
return BadRequest();
}
}
}
Startup.cs:
private void ConfigureContainer(ContainerBuilder builder)
{
var contextOptions = new DbContextOptionsBuilder<MovieCommandContext>()
.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))
.Options;
builder.RegisterType<MovieCommandContext>()
.WithParameter("options", contextOptions);
builder.RegisterType<MovieQueryContext>()
.AsSelf()
.WithParameter("connectionString",Configuration.GetConnectionString("DefaultConnection"));
builder.RegisterType<MovieCommandRepository>().As<ICommandRepository<Movie>>();
builder.RegisterType<MovieQueryRepository>().As<IQueryRepository<Movie>>();
}
Point 1:
You should return an IActionResult to return a propper Http response, instead of returning the Task<IEnumerable<Movie>>. That way you guarantee the S and the I of SOLID principles
Point 2 & 3:
see here: Entity Framework Core service default lifetime
Point 4:
IQueryRepository as some bad methods names. The names are tight coupled with domain concepts and they should not.
You are failing the Separation of concerns ( the S of SOLID).
ICommandRepository as an Add method that is being expose to some controller and not being used ( same as Update) here you are failing on the Interface segregation.
MovieQueryContext does not implement IDisposable pattern correctly please see here!
MovieQueryContext is different from MovieCommandContext on the way it initializes. Why? You should try to be coherent the way you design you types because it will give you reusability and apply the DRY principle.
Consider the effort you will need to to if the access to the database change to mongodb. Or if the access to the database changes to a remote service How many changes, and where do you do does changes to support that?
If Movie is a Domain Type it should not have attributes to any specific database access. keep it POCO as possible.
Point 5:
To design your API consider this post. The way you inject your dependencies should consider the lifetime of those objects. Keep in mind that in aspnet.core ApiControllers lifetime is per request. The way you manage your resources to access database should take that into consideration.
If you are considering CQRS, the controllers should be diferent. Keeping in mind the Separation of concerns regarding those responsabilities. One controller would have the responsability to expose some query API, and the other to process commands. There are good frameworks to support CQRS see this scott hanselman post.
Constraints exists on Route attribute not on Verbs.
Logging and Exception handling should be done on an ActionAttribute or on some Especific Middleware, because they are considered to be cross cutting concerns.
Delete Action does not comply to the Http protocol. please consider http rfc:
GetMoviesByTitle Action does not have the name parameter.
Point 6:
Unit tests should test business logic, mocking all the external dependencies with values relevant to the test in place. TDD methodology considers 3 main steps ( here for more details):
the first step consists on implementing the unit tests so it fails
Iterate on implementation of the method being test until it passes with success
Improve the implementation of the method being test
If you want to test your ApiController as being used with all the middleware integrated you need to have that environment put in place without using an actual server that open ports. To do that please consider the usage of TestServer ( see here and here )
1. What is recommended return type between "Task< IActionResult >" and "Task< IEnumerable < Movie > >"?
Even though the API allows you yo use the interface IActionResult, I wouldn't use it at all. Why? Semantics, the only way to know what the true return is, is to see the implementation. It's clearer if the returns is Task< IEnumerable< Movie>>.
If you need to throw a BadRequest or other http code, use the asp.net pipeline to handle this for you. See Notes below.
When using whatever tool to generate some sort of documentation of this API it won't help hiding the real result.
2. object Scope of the dependencies in startup class for my project?
Avoid sharing state between calls, to avoid future issues with synchronization just stick to scope dependencies per request. This may be a performance issue if you have a lot of requests, you can always change this later on. If it's an issue at all.
3. I really need UnitOfWork for this given project structure?
4. What are the flaws if I follow this design?
5. Is there any better way to design this API?
In hope of answering the above 3 questions. The problem I see is extending the functionality around Movie model. e.g. add a fourth action on ICommandRepository.
It seams it will grow vertically. It will only be a problem if multiple classes implement this interface, because they will all need to change. (Interface Segregation Principle)
A way to solve this is to use the Mediator pattern. Your controller will receive the mediator and the mediator will deliver the message to whoever handles it. With this type of solution you could have a class per operation and therefore your system can grow horizontally as new classes are added to the system. (Open Close Principle)
In time, you'll see that a lot of functionality can be reused and adding features is just a matter of configuration.
6. As TDD do I need write test cases for API layer(Controller) and Infrastructure layer only or Domain Layer (it doesn't have any logic) as well?
The idea of Testing in general is to test behavior, when TDDing that should be your mindset. In my experience I found that testing the whole behavior is better than multiple parts of the same behavior.
In this case, the API Layer is part of the infrastructure as is the persistence layer. They should have their own tests, the business rules (Application layer) should have their own tests. The application layer is what you want to last forever. The Api will change as technologies appear (windows forms, web forms, web apis, etc.) Regarding databases as well, you don't know if you want to stick with EF forever.
If the domain layer doesn't provide any behavior then there is nothing to test.
7. What are the scenario I must include in my controller unit test?
I would test using asp.net TestHost:
https://learn.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-2.2
Test the if routing is correct, test failing scenarios and successful scenarios.
Some notes:
An exception in the Controller does not mean a BadRequest.
Logging is a cross cutting concern, don't just do it everywhere.
Either use the asp.net pipeline or just move this concern to
application layer.
It appears that MovieQueryRepository does nothing, so you don't need it.
This is just some remarks about your questions, there is much more to it. Just remember to keep things simple and organized.
Hope it helped, let me know!
I am a newbie in ASP.NET, and currently learning ASP.NET Identity. I know it's built on top of OWIN implementation by Microsoft, and I am also still learning that too. So, I came across the extension method CreatePerOwinContext in the Owin startup code, and I don't see a clear purpose of using it. Is it some kind of dependency injection container? What is the real purpose of the method? In what case it should be applied?
CreatePerOwinContext registers a static callback which your application will use to get back a new instance of a specified type.
This callback will be called once per request and will store the object/objects in OwinContext so that you will be able to use them throughout the application.
Let's say you have defined your own implementation of IdentityDbContext:
public class ApplicationDatabaseContext : IdentityDbContext<MyApplicationUser, MyRole, Guid, MyUserLogin, MyUserRole, MyUserClaim>
{
public ApplicationDatabaseContext() : base("<connection string>")
{
}
public static ApplicationDatabaseContext Create()
{
return new ApplicationDatabaseContext();
}
protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// Customize your table creation here.
#region USERS - INFOS
modelBuilder.Entity<UserInfo>()
.Property(p => p.FirstName)
.HasColumnType("varchar")
.HasMaxLength(70);
modelBuilder.Entity<UserInfo>()
.Property(p => p.LastName)
.HasColumnType("varchar")
.HasMaxLength(70);
modelBuilder.Entity<UserInfo>()
.Property(p => p.Address)
.HasColumnType("varchar")
.HasMaxLength(100);
modelBuilder.Entity<UserInfo>()
.Property(p => p.City)
.HasColumnType("varchar")
.HasMaxLength(100);
modelBuilder.Entity<UserInfo>()
.ToTable("UsersInfo");
#endregion
}
public DbSet<UserInfo> UsersInfo { get; set; }
}
and your implementation of UserManager:
public class ApplicationUserManager : UserManager<MyApplicationUser, Guid>
{
public ApplicationUserManager(IUserStore<MyApplicationUser, Guid> store) : base(store)
{
}
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(new MyUserStore(context.Get<ApplicationDatabaseContext>()));
manager.UserValidator = new UserValidator<MyApplicationUser, Guid>(manager)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
};
manager.PasswordValidator = new PasswordValidator()
{
RequiredLength = 6,
RequireNonLetterOrDigit = false,
// RequireDigit = true,
RequireLowercase = false,
RequireUppercase = false,
};
var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
manager.UserTokenProvider = new DataProtectorTokenProvider<MyApplicationUser, Guid>(dataProtectionProvider.Create("PasswordReset"));
}
return (manager);
}
}
In your Owin Startup you will register the callback:
// IAppBuilder app
app.CreatePerOwinContext<ApplicationDatabaseContext>(ApplicationDatabaseContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
which will call the static method:
public static ApplicationDatabaseContext Create()
{
return new ApplicationDatabaseContext();
}
and
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
...
}
Now you will be able to access your database context and user manager in a simple straightforward way:
ApplicationDatabaseContext dbContext = context.OwinContext.Get<ApplicationDatabaseContext>();
ApplicationUserManager userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();
In your ApiController (if you're using WebApi):
IAuthenticationManager authenticationManager = HttpContext.Current.GetOwinContext().Authentication;
ApplicationUserManager applicationUserManager = HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();
What is the real purpose of the method? In what case it should be
applied?
To answer your question more directly, this is useless.
It's some sort of IoC factory, which some people like using.
This one makes you use theirs (IoC) over your choice.
(I don't like IoC, it feels like an anti-pattern for people who want to feel warm and fuzzy and use the term "architecture".)
But seriously, this pattern doesn't IoC interfaces, it IoC static factory functions! Who's idea was that? Why not just use the Factory function yourself? Now you have to remember (Google) an extra API call, and when you press F12 on Get, it takes you nowhere helpful.
What should you do instead then?
Personally, I'm a fan of using OO for this, remember OO? Pepperidge farm remembers. With OO, you remain in control, you can debug, log, and you can extend.
public class BaseApiController : ApiController
{
private AppDbContext _db = null;
protected AppDbContext db
{
get
{
if (_db == null)
{
_db = AppDbContext.Create(); //Hey look a proper factory that you can extend with other overloads! And I can debug this line - neat!
}
return _db;
}
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (_db != null)
_db.Dispose();
}
}
}
All this could be a waste of time, if someone finds some documentation why Microsoft engineers put this in, they might have a good reason why, but I doubt it, so let's upvote this answer in the meantime.
UPDATE 1
Here's the why, why it's there for Microsoft: https://blogs.msdn.microsoft.com/webdev/2014/02/12/per-request-lifetime-management-for-usermanager-class-in-asp-net-identity/
Basically, the UserManager and all them are built for this kind of structure. The Security checks occur in the pipeline, so why not have a singleton linked to the request, to reduce waste? Because it's hidden.
I would still recommend creating your own instance of the db context on a baseclass, it makes it much cleaner to use. If you really want, you can have a property in your baseclass which retrieves the singleton from the OwinContext.
How much time do we waste trying to work out these fancy APIs, and Authorise attributes and the like, when all we want to do is:
public void DoSomething()
{
DemandAuthenticated();
DemandAuthorised(typeof(somethingClass), "DoSomething");
}
Clearly, I prefer verbose code you can see.
Update 2
EF contexts should not be held as singletons, and certainly not through any IoC or repository pattern.
Generally, yes IoC can be good in situations. But specifically for a dbContext? No.
1) EF DB contexts are a unit of work, they should be short-lived. If you keep them running for a long time, the object cache will slow down queries, and updates/inserts to the underlying database get slower. It's designed to have short lifetime.
2) Also, EF contexts are already loosely coupled. You can change the RDBMS behind a context in the connection string, you can even use memory-only.
3) EF has LINQ which is very flexible, expressive, and type safe.
4) Database is not a business-level service for IoC it's a tool that services use to communicate with the database. Perhaps, You might have some kind of service IEmail that is accessed via IoC. But it should access the internal database using a new EF context that is disposed promptly after completion of queries.
5) Given 1-4 above, we certainly don't want any intermediate Interface layers (Service or Repository) to spoil all the benefits of using EF in the first place.
you may use typeof to get the name like this:
HttpContext.GetOwinContext().Get<ApplicationDbContext>(typeof(ApplicationDbContext).ToString());
I am actually working in an ASP.Net MVC 4 web application where we are using NInject for dependency injection. We are also using UnitOfWork and Repositories based on Entity framework.
We would like to use Quartz.net in our application to start some custom job periodically. I would like that NInject bind automatically the services that we need in our job.
It could be something like this:
public class DispatchingJob : IJob
{
private readonly IDispatchingManagementService _dispatchingManagementService;
public DispatchingJob(IDispatchingManagementService dispatchingManagementService )
{
_dispatchingManagementService = dispatchingManagementService ;
}
public void Execute(IJobExecutionContext context)
{
LogManager.Instance.Info(string.Format("Dispatching job started at: {0}", DateTime.Now));
_dispatchingManagementService.DispatchAtomicChecks();
LogManager.Instance.Info(string.Format("Dispatching job ended at: {0}", DateTime.Now));
}
}
So far, in our NInjectWebCommon binding is configured like this (using request scope):
kernel.Bind<IDispatchingManagementService>().To<DispatchingManagementService>();
Is it possible to inject the correct implementation into our custom job using NInject ? and how to do it ? I have read already few posts on stack overflow, however i need some advises and some example using NInject.
Use a JobFactory in your Quartz schedule, and resolve your job instance there.
So, in your NInject config set up the job (I'm guessing at the correct NInject syntax here)
// Assuming you only have one IJob
kernel.Bind<IJob>().To<DispatchingJob>();
Then, create a JobFactory: [edit: this is a modified version of #BatteryBackupUnit's answer here]
public class NInjectJobFactory : IJobFactory
{
private readonly IResolutionRoot resolutionRoot;
public NinjectJobFactory(IResolutionRoot resolutionRoot)
{
this.resolutionRoot = resolutionRoot;
}
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
// If you have multiple jobs, specify the name as
// bundle.JobDetail.JobType.Name, or pass the type, whatever
// NInject wants..
return (IJob)this.resolutionRoot.Get<IJob>();
}
public void ReturnJob(IJob job)
{
this.resolutionRoot.Release(job);
}
}
Then, when you create the scheduler, assign the JobFactory to it:
private IScheduler GetSchedule(IResolutionRoot root)
{
var schedule = new StdSchedulerFactory().GetScheduler();
schedule.JobFactory = new NInjectJobFactory(root);
return schedule;
}
Quartz will then use the JobFactory to create the job, and NInject will resolve the dependencies for you.
Regarding scoping of the IUnitOfWork, as per a comment of the answer i linked, you can do
// default for web requests
Bind<IUnitOfWork>().To<UnitOfWork>()
.InRequestScope();
// fall back to `InCallScope()` when there's no web request.
Bind<IUnitOfWork>().To<UnitOfWork>()
.When(x => HttpContext.Current == null)
.InCallScope();
There's only one caveat that you should be aware of:
With incorrect usage of async in a web request, you may mistakenly be resolving a IUnitOfWork in a worker thread where HttpContext.Current is null. Now without the fallback binding, this would fail with an exception which would show you that you've done something wrong. With the fallback binding however, the issue may present itself in an obscured way. That is, it may work sometimes, but sometimes not. This is because there will be two (or even more) IUnitOfWork instances for the same request.
To remedy this, we can make the binding more specific. For this, we need some parameter to tell us to use another than InRequestScope(). Have a look at:
public class NonRequestScopedParameter : Ninject.Parameters.IParameter
{
public bool Equals(IParameter other)
{
if (other == null)
{
return false;
}
return other is NonRequestScopedParameter;
}
public object GetValue(IContext context, ITarget target)
{
throw new NotSupportedException("this parameter does not provide a value");
}
public string Name
{
get { return typeof(NonRequestScopedParameter).Name; }
}
// this is very important
public bool ShouldInherit
{
get { return true; }
}
}
now adapt the job factory as follows:
public class NInjectJobFactory : IJobFactory
{
private readonly IResolutionRoot resolutionRoot;
public NinjectJobFactory(IResolutionRoot resolutionRoot)
{
this.resolutionRoot = resolutionRoot;
}
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
return (IJob) this.resolutionRoot.Get(
bundle.JobDetail.JobType,
new NonrequestScopedParameter()); // parameter goes here
}
public void ReturnJob(IJob job)
{
this.resolutionRoot.Release(job);
}
}
and adapt the IUnitOfWork bindings:
Bind<IUnitOfWork>().To<UnitOfWork>()
.InRequestScope();
Bind<IUnitOfWork>().To<UnitOfWork>()
.When(x => x.Parameters.OfType<NonRequestScopedParameter>().Any())
.InCallScope();
This way, if you use async wrong, there'll still be an exception, but IUnitOfWork scoping will still work for quartz tasks.
For any users that could be interested, here is the solution that finally worked for me.
I have made it working doing some adjustment to match my project. Please note that in the method NewJob, I have replaced the call to Kernel.Get by _resolutionRoot.Get.
As you can find here:
public class JobFactory : IJobFactory
{
private readonly IResolutionRoot _resolutionRoot;
public JobFactory(IResolutionRoot resolutionRoot)
{
this._resolutionRoot = resolutionRoot;
}
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
try
{
return (IJob)_resolutionRoot.Get(
bundle.JobDetail.JobType, new NonRequestScopedParameter()); // parameter goes here
}
catch (Exception ex)
{
LogManager.Instance.Info(string.Format("Exception raised in JobFactory"));
}
}
public void ReturnJob(IJob job)
{
}
}
And here is the call schedule my job:
public static void RegisterScheduler(IKernel kernel)
{
try
{
var scheduler = new StdSchedulerFactory().GetScheduler();
scheduler.JobFactory = new JobFactory(kernel);
....
}
}
Thank you very much for your help
Thanks so much for your response. I have implemented something like that and the binding is working :):
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
var resolver = DependencyResolver.Current;
var myJob = (IJob)resolver.GetService(typeof(IJob));
return myJob;
}
As I told before I am using in my project a service and unit of work (based on EF) that are both injected with NInject.
public class DispatchingManagementService : IDispatchingManagementService
{
private readonly IUnitOfWork _unitOfWork;
public DispatchingManagementService(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
}
Please find here how I am binding the implementations:
kernel.Bind<IUnitOfWork>().To<EfUnitOfWork>()
kernel.Bind<IDispatchingManagementService>().To<DispatchingManagementService>();
kernel.Bind<IJob>().To<DispatchingJob>();
To resume, the binding of IUnitOfWork is done for:
- Eevery time a new request is coming to my application ASP.Net MVC: Request scope
- Every time I am running the job: InCallScope
What are the best practices according to the behavior of EF ? I have find information to use CallInScope. Is it possible to tell NInject to get a scope ByRequest everytime a new request is coming to the application, and a InCallScope everytime my job is running ? How to do that ?
Thank you very much for your help
I've looked at 'Messenger and references' discussion, but I'm writing a new topic, because my issue is not technical, and I don't want to offtop there.
I've encountered a doubt - Have I to code cleanup()/RequestCleanup() method implementation to unregister previously registered Messenger in my viewmodel class? I'm afraid of memory leaks in the future.
I think I've found the documentation not to be enough bright for me.
Description of Messenger.Register is: '... Registering a recipient does not create a hard reference to it, so if this recipient is deleted, no memory leak is caused.'
1) Is this mean that I don't have to take care of it and implement-develop following solutions?
On the other hand, we can find in the code of GalaSoft.MvvmLight.ViewModelBase abstract class the short info about the Cleanup() method:
//
// Summary:
// Unregisters this instance from the Messenger class.
// To cleanup additional resources, override this method, clean up and then
// call base.Cleanup().
public virtual void Cleanup();
so 2) Is only invoking a Cleanup enough to unregister class-instance out of the Messenger?
3) Or maybe I have to invoke Messenger.Default.Unregister(this); in the body of a Cleanup method?
4) In the Unregister(Object) doc we read 'Unregisters a messager recipient completely' - what does the 'completely' mean?
I'm very sorry if my post seems to have out of the context quotes, I wanted to point out what I'm more interested in.
EDIT 1:
Hello Joel, thanks for reply. I've got several questions:
1) I have used your code. There's defined override void Cleanup() in CustomerMasterViewModel. Where to call it? Should I declare destructor in this case or maybe the ViewModelBase has an automatic mechanism for invoking the Cleanup()?
2) I have in my project another base class from a different toolkit, so my VMs cannot derive from both at the same time. How to organise your code to get the same effect by implementing only ICleanup interface?
public class CustomerMasterViewModel : SomeBaseClass, ICleanup
{
public CustomerMasterViewModel()
{
Messenger.Default.Register<Message>(this, this.MessageReceived);
}
#region messages
private void MessageReceived(Message obj)
{
//do something
}
#endregion
#region helper methods
public override void Cleanup()
{
//base.Cleanup();//there's no implementaction in an interface
ViewModelLocator.Cleanup();
}
#endregion
}
You have to invoke the Cleanup() method in GalaSoft.MvvmLight.ViewModelBase on each of you view models you wan't to dispose don't need any longer.
Example:
Let say your application has a tab control with different tabs. Each of your tabs displays a UserControl which has a dedicated ViewModel. The user has the ability to close a tabs which causes the underlining ViewModel to become obsolete.
Want you want to do now is to clean up the ViewModel calling the Cleanup() method in GalaSoft.MvvmLight.ViewModelBase. This will unregister ALL registered messages. The GarbageCollector will take care of you viewmodel if there are no other references.
Assuming you use the ViewModelLocator which also comes with the MVVM Light Framework you're not done yet because at least the ViewModelLocator itself has a reference to your viewmodel! Therefore the Garbage Collector can't finalize your viewmodel.
But it also has another side effect. When the user reopens the tab (Lets say the user is able to do so) the UserControl is loaded again and the ViewModelLocator will give you the same ViewModel instance. The only difference is that there are not registered messages because you cleaned them by calling the CleanUp() method.
What you need is a new instance of your ViewModel. To achieve this you have to clean up your ViewModelLocator as well!
You have to unregister them (Unregister<CustomerMasterViewModel>()) one by one or simply call Reset() which will unregister all viewmodels.
Then there should be no other reference to you viewmodel and the GarbageCollector can finally take care about it.
Here is an example to do so:
ViewModelLocator:
public class ViewModelLocator
{
public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
SimpleIoc.Default.Register<CustomerMasterViewModel>();
}
public CustomerMasterViewModel CustomerMasterViewModel
{
get
{
return ServiceLocator.Current.GetInstance<CustomerMasterViewModel>();
}
}
public static void Cleanup()
{
SimpleIoc.Default.Reset();
//Don't forget to register them if the user attempts to open the new.
//The viewmodel initialization is lazy by default so this comes at no costs.
SimpleIoc.Default.Register<CustomerMasterViewModel>();
}
}
ViewModel
public class CustomerMasterViewModel : ViewModelBase
{
public CustomerMasterViewModel()
{
Messenger.Default.Register<Message>(this, this.MessageReceived);
}
#region messages
private void MessageReceived(Message obj)
{
//do something
}
#endregion
#region helper methods
public override void Cleanup()
{
base.Cleanup();
ViewModelLocator.Cleanup();
}
#endregion
}
In Short:
1) As far as i understood clean up is necessary after you're done.
2) Yes, calling the Cleanup() method in GalaSoft.MvvmLight.ViewModelBase will unregister all messages for this viewmodel.
3) No, see above.
4) Completely means it will unregister ALL registered messages.
I'm trying to work out how to complete my implementation of the Repository pattern in an ASP.NET web application.
At the moment, I have a repository interface per domain class defining methods for e.g. loading and saving instances of that class.
Each repository interface is implemented by a class which does the NHibernate stuff. Castle Windsor sorts out the DI of the class into the interface according to web.config. An example of an implemented class is provided below:
public class StoredWillRepository : IStoredWillRepository
{
public StoredWill Load(int id)
{
StoredWill storedWill;
using (ISession session = NHibernateSessionFactory.OpenSession())
{
storedWill = session.Load<StoredWill>(id);
NHibernateUtil.Initialize(storedWill);
}
return storedWill;
}
public void Save(StoredWill storedWill)
{
using (ISession session = NHibernateSessionFactory.OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
session.SaveOrUpdate(storedWill);
transaction.Commit();
}
}
}
}
As pointed out in a previous thread, the repository class needs to accept an unit of work container (i.e. ISession) rather than instantiating it in every method.
I anticipate that the unit of work container will be created by each aspx page when needed (for example, in a property).
How do I then specify that this unit of work container instance is to be passed into the constructor of StoredWillRepository when Windsor is creating it for me?
Or is this pattern completely wrong?
Thanks again for your advice.
David
I have a persistence framework built on top of NHibernate that is used in a few Web apps. It hides the NH implementation behind an IRepository and IRepository<T> interface, with the concrete instances provided by Unity (thus I could in theory swap out NHibernate for, say, Entity Framework fairly easily).
Since Unity doesn't (or at least the version I'm using doesn't) support the passing in of constructor parameters other than those that are dependency injections themselves, passing in an extant NH ISession isn't possible; but I do want all objects in the UOW to share the same ISession.
I solve this by having a controlling repository class that manages access to the ISession on a per-thread basis:
public static ISession Session
{
get
{
lock (_lockObject)
{
// if a cached session exists, we'll use it
if (PersistenceFrameworkContext.Current.Items.ContainsKey(SESSION_KEY))
{
return (ISession)PersistenceFrameworkContext.Current.Items[NHibernateRepository.SESSION_KEY];
}
else
{
// must create a new session - note we're not caching the new session here... that's the job of
// BeginUnitOfWork().
return _factory.OpenSession(new NHibernateInterceptor());
}
}
}
}
In this example, PersistenceFrameworkContext.Current.Items accesses an IList<object> that is stored either ThreadStatic if not in a Web context, or within HttpContext.Current.Items if it is in a Web context (to avoid thread-pool problems). The first call to the property instantiates the ISession from the stored factory instance, subsequent calls just retrieve it from storage. The locking will slow things down slightly but not as much as just locking an appdomain-scoped static ISession instance.
I then have BeginUnitOfWork and EndUnitOfWork methods to take care of the UOW - I have specifically disallowed nested UOWs because frankly they were a pain to manage.
public void BeginUnitOfWork()
{
lock (_lockObject)
{
if (PersistenceFrameworkContext.Current.Items.ContainsKey(SESSION_KEY))
EndUnitOfWork();
ISession session = Session;
PersistenceFrameworkContext.Current.Items.Add(SESSION_KEY, session);
}
}
public void EndUnitOfWork()
{
lock (_lockObject)
{
if (PersistenceFrameworkContext.Current.Items.ContainsKey(SESSION_KEY))
{
ISession session = (ISession)PersistenceFrameworkContext.Current.Items[SESSION_KEY];
PersistenceFrameworkContext.Current.Items.Remove(SESSION_KEY);
session.Flush();
session.Dispose();
}
}
}
Finally, a pair of methods provide access to the domain-type-specific repositories:
public IRepository<T> For<T>()
where T : PersistentObject<T>
{
return Container.Resolve<IRepository<T>>();
}
public TRepository For<T, TRepository>()
where T : PersistentObject<T>
where TRepository : IRepository<T>
{
return Container.Resolve<TRepository>();
}
(Here, PersistentObject<T> is a base class providing ID and Equals support.)
Access to a given repository is thus in the pattern
NHibernateRepository.For<MyDomainType>().Save();
This is then facaded over such that you can use
MyDomainType.Repository.Save();
Where a given type has a specialised repository (ie needs more than it can get from IRepository<T>) then I create an interface deriving from IRepository<T>, an extending implementation inheriting from my IRepository<T> implementation, and in the domain type itself I override the static Repository property using new
new public static IUserRepository Repository
{
get
{
return MyApplication.Repository.For<User, IUserRepository>();
}
}
(MyApplication [which is called something less noddy in the real product] is a facade class which takes care of supplying the Repository instance via Unity so you have no dependency on the specific NHibernate repository implementation within your domain classes.)
This gives me full pluggability via Unity for the repository implementation, easy access to the repository in code without jumping through hoops, and transparent, per-thread ISession management.
There's lots more code than just what's above (and I've simplified the example code a great deal), but you get the general idea.
MyApplication.Repository.BeginUnitOfWork();
User user = User.Repository.FindByEmail("wibble#wobble.com");
user.FirstName = "Joe"; // change something
user.LastName = "Bloggs";
// you *can* call User.Repository.Save(user), but you don't need to, because...
MyApplication.Repository.EndUnitOfWork();
// ...causes session flush which saves the changes automatically
In my Web app, I have session-per-request, so BeginUnitOfWork and EndUnitOfWork get called in BeginRequest and EndRequest respectively.
I have a pretty similar structure to yours, and here's how I solve your question:
1) To specify my container on each method, I have a separate class ("SessionManager") which I then invoke via a static property. By doing so, here's an example using my Save implementation:
private static ISession NHibernateSession
{
get { return SessionManager.Instance.GetSession(); }
}
public T Save(T entity)
{
using (var transaction = NHibernateSession.BeginTransaction())
{
ValidateEntityValues(entity);
NHibernateSession.Save(entity);
transaction.Commit();
}
return entity;
}
2) My container is not created on each ASPX page. I instantiate all of my NHibernate goodness on the global.asax page.
** A few more things spring up **
3) You don't need to have a helper to instantiate the Load. You might as well use Get instead of Load. More information # Difference between Load and Get.
4) Using your current code, you would have to repeat pretty much the same code for each domain object you need (StoredWillRepository, PersonRepository, CategoryRepository, etc..?), which seems like a drag. You could very well use a generic class to operate over NHibernate, like:
public class Dao<T> : IDao<T>
{
public T SaveOrUpdate(T entity)
{
using (var transaction = NHibernateSession.BeginTransaction())
{
NHibernateSession.SaveOrUpdate(entity);
transaction.Commit();
}
return entity;
}
}
In my implementation, I could then use something like:
Service<StoredWill>.Instance.SaveOrUpdate(will);
Technically, the answer to my question is to use the overload of container.Resolve which allows you to specify the constructor argument as an anonymous type:
IUnitOfWork unitOfWork = [Code to get unit of work];
_storedWillRepository = container.Resolve<IStoredWillRepository>(new { unitOfWork = unitOfWork });
But let's face it, the answers provided by everyone else have been much more informative.