IoC, UnitOfWork with Ninject and Entity Framework - c#

Im trying to implement a generic repository to my service classes.
But when i try to bind my DbConext in Web layer, i need to reference Entity Framework.
My DbContext
public partial class SalesDbContext : DbContext, IUnitOfWork
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
public DbSet<Activity> Activities { get; set; }
/// <summary>
/// Allows saving changes via the IUnitOfWork interface.
/// </summary>
void IUnitOfWork.Commit()
{
base.SaveChanges();
}
My IUnitOfWork
public interface IUnitOfWork
{
/// <summary>
/// Saves changes to all objects that have changed within the unit of work.
/// </summary>
void Commit();
}
My Repository
public class Repository
{
protected IUnitOfWork UnitOfWork { get; set; }
protected SalesDbContext Context
{
get { return (SalesDbContext)this.UnitOfWork; }
}
public Repository(IUnitOfWork unitOfWork)
{
if (unitOfWork == null) throw new ArgumentNullException("unitOfWork");
this.UnitOfWork = unitOfWork;
}
private DbSet<TEntity> GetDbSet<TEntity>() where TEntity : class
{
return this.Context.Set<TEntity>();
}
protected IEnumerable<TEntity> GetAll<TEntity>() where TEntity : class
{
return this.GetDbSet<TEntity>()
.AsEnumerable();
}
protected virtual void SetEntityState(object entity, EntityState entityState)
{
this.Context.Entry(entity).State = entityState;
}
}
And last my Ninject config
private static void RegisterServices(IKernel kernel)
{
IUnitOfWork unitOfWork = new SalesDbContext();
kernel.Bind<IUnitOfWork>().ToConstant(unitOfWork);
kernel.Bind<IMarketService>().To<MarketService>();
}
The problem is that Ninject wants the references to Entity Framework, but i dont want to add it here, it belongs to the data layer.
And do you think the ToConstant implementation for DbContext will cause problem?

If you do not want to reference the EntityFramework from the top level (e.g. web) project, how would you build your application? The top level project needs to have references to all underlying dependencies, so they could be put inside bin folder, in the case of web app.
And definitely it is not Ninject, who wants that reference. It is because you are using classes, that depends on EntityFramework in that project.
There is no problem to have references from the top layer (through middle) to the bottom layer. It could be (design) problem, if it would be other way round (e.g. to have reference from data layer to System.Web).
UPDATE
As OP stated in his comment. There is one possible solution to avoid referencing dependencies of the bottom layer (like EF) from the top layer using the ninject.extensions.xml. It will work only if the intention was to make ninject configuration in the top layer project, but the project itself is not referencing (using) any of the bottom layer classes with dependencies. Also the EF have to be in GAC.
It is not a good conception to bind your DbContext ToConstant() as long as it implements IDisposable. DbContext should be bound in the shortest possible Scope meaningful for the application (e.g. InRequestScope() for web app). Ninject will dispose it at the end of the Scope.
If you let DbContext bound ToConstant, it will hold one connection to database per whole application lifecycle. You can get into trouble with concurrency issues and the DbContext could become inconsistent, when accessed by multiple threads, because it wont be able to keep up on object synchronization.

Related

UnitOfWork with Repository and Entity Framework

I am working on a project with Entity Framework where i have implemented Repository pattern and DI (Microsoft Unity), now to maintain the database transactions i want to implement the UnitOfWork pattern, but i am totally confused about how shall i implement it in my current project, i google around few posts, but could not find anything doable with my existing project.
Below is the EF and Repository structure along with DI (Microsoft Unity).
Entities:
public class GenericDo
{
public DateTime CreatedDate {get;set;}
public string CreatedBy {get;set;}
}
public class UsersDo : GenericDo
{
public int UserId {get;set;}
public string Username {get;set;}
....
}
public class UserProfileDo : GenericDo
{
public int Id {get;set}
public int UserId {get;set;}
public string Address {get;set;}
....
}
Interface:
public interface IGenericDao : IGenericDao<GenericDo> {}
public interface IGenericDao<T>
{
void Add(T entity);
T Get(object Id);
....
}
public interface IUsersDao : IUsersDao<UsersDo> {}
public interface IUserProfileDao : IUserProfileDao<UserProfileDo>{}
Interface Implementation:
public class GenericDao<T> : IGenericDao<T> where T : class
{
private readonly DataContext context;
public GenericDao(DataContext _context)
{
this.context = _context;
}
public void Add(T entity)
{
context.Set<T>().Add(entity);
}
public T Get(object Id)
{
return context.Set<T>().Find(Id);
}
}
public class UsersDao : GenericDao<UsersDo>, IUsersDao
{
public UsersDao(DataContext context) : base (context){}
}
public class UserPorfileDao : GenericDao<UserProfileDo>, IUserProfileDao
{
public UserPorfileDao(DataContext context) : base (context){}
}
Dependency Injection Setup in Global.asax.
var container = this.AddUnity();
container.RegisterType<IUsersDao, UsersDao>();
container.RegisterType<IUserProfileDao, UserProfileDao>();
Now in my main webpage(ASP.Net)
public partial class Default : System.Web.UI.Page
{
private readonly IUsersDao usersDao;
private readonly IUserProfileDao userProfileDao;
public Default(IUsersDao _userDao, IUserProfileDao _userProfileDao)
{
this.usersDao = _userDao;
this.userProfileDao = _userProfileDao;
}
// Now for testing purpose, i update record.
protected void Page_Load(object sender, EventArgs e)
{
UsersDo user = usersDao.Get(1);
user.Username = "new system";
UserProfileDo userProfile = userProfileDao.Get(1);
userProfile.Address = "new address";
// Now here i am confused about setting up common Save method to update database with transaction.
}
}
EntityFramework's DbContext already implements Unit of Work, so it is not necessary to add yet another layer of abstraction to implement this.
One could even doubt if creating a Repository pattern is actually helpful if you're using Entity Framework. Instead of using a layered architecture and using a Repository, you could investigate whether it is not better to use a more sliced architecture and use the DbContext directly.
Also, what is the benefit of having a 'Generic Dao' that just delegates calls to Entity Frameworks DbContext ? It's just yet another level of abstraction which adds extra complexity but doesn't give you any added value.
Unit of work ecapsulates the database operations in a single object and keeps track of them. In Entity Framework DbContext implements this behaviour and DbSet<> implements the repository. The reason why people create their own wrappers around is to be able to swap Entity Framework for another ORM, if needed or to mock Entity Framework for testing,.
UnitOfWork pattern is used with Entity Framework.
The repository and unit of work patterns are intended to create an abstraction layer between the data access layer and the business logic layer of an application. Implementing these patterns can help insulate your application from changes in the data store and can facilitate automated unit testing or test-driven development (TDD).
First step is to create repositories. Repository is a class which exposes methods to business layer
Second step: You can create UnitOfWork implementation as shown below. There are properties corresponding to every repository. Then you inject Unit of Work in your business layer to use the repository methods.
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;
}
}
}
refer documentation at: https://learn.microsoft.com/en-us/aspnet/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application

Implementing a Simple Repository, Unit of Work with Dependency Injection

I have been trying to create a Repository Pattern along with Dependency injection, But Looks like I am missing some simple step. Here is my code
public class HomeController
{
private readonly ILoggingRepository _loggingRepository;
public HomeController(ILoggingRepository loggingRepository)
{
_loggingRepository = loggingRepository;
}
public void MyMethod()
{
string message = "MyMessage Called";
_loggingRepository .LogMessage(message);
}
}
// ILoggingRepository.cs
public interface ILoggingRepository
{
void LogMessage(string message);
}
// LoggingRepository.cs
public class LoggingRepository : ILoggingRepository
{
public void LogMessage(string message)
{
using (var dbContext = new DbContext())
{
var serviceLog = new Log() { Message = message, Logged = DateTime.UtcNow };
dbContext.Logs.Add(serviceLog);
dbContext.SaveChanges();
}
}
}
This works perfectly all right so far, but the problem arises when i make more than one repository calls.
Now I know that Entity framework 6.0 has inbuilt unit of work representation so I didn't created a UnitofWork Interface or class
But the problem appears when I do something like this in two different transactions. Lets say
Area area = _areaRepository.GetArea(); // Line 1
area.Name = "NewArea"; // Line 2
_areaRepository.SaveArea(area); // Line 3
now because it _areaRepository creates a new DbContext in Line 3, it doesn't changes the name of area as it doesn't consider EntityState.Modified
I have to explicitly set that, which isn't correct.
So I guess I need to do all this in single Transaction, Where I am doing wrong here ?
What is the correct and best way to achieve this, Should I inject my DbContext also into the repository?
This is how I doit all times:
If dont use Repository or Unit of Work layers, because Entity Framework db Context already implements those patterns. So, I only have a Service layer:
public interface IBaseService<VO, ENT>{
IQueryable<VO> GetAll();
VO Get(object id);
}
public abstract class BaseService<VO, ENT> : IBaseService<VO, ENT>{
MyContext db;
public BaseService(MyContext db){
this.db = db;
}
public IQueryable<VO> GetAll(){
return db.Set<ENT>().ProjectTo<VO>();
}
}
A service class have a dbContext injected in the constructor. This classes are located in a Service library. Then, how the dbContext and the service are resolved is a problem of the project who will be using them. The ProjectTo method is an extension for IQueryable from the Automapper Nuget. For example:
A Windows Service needs all services instance in the same thread shares the same dbContext. So, in the windows service project, I use Ninject https://www.nuget.org/packages/Ninject/4.0.0-beta-0134, this library is a dependency resolver, wich I use to configure how dependencies are builded, creating a Kernel, like this:
var kernel = new StandardKernel();
kernel.Bind<MyContext>().ToSelf().InThreadScope();
kernel.Bind<IServiceImplInterface>().To<ServiceImplClass>().InThreadScope();
I you are creating a Web project, you will need to install a aditional nuget (Ninject.WebCommon, Ninject.Web.COmmon.WebHost, Ninject.MVC5) to provide a .InRequestScope() method to the binding configuration, like this:
var kernel = new StandardKernel();
kernel.Bind<MyContext>().ToSelf().InRequestScope();
kernel.Bind<IServiceImplInterface>().To<ServiceImplClass>().InRequestScope();
You need setup those kernel when the app startup. In a web project is in the global.asax, in a windows service project, should be in the Service constructor:
You can visit www.ninject.org/learn.html to learn more about ninject. But, there are othres like Autofac or Caste Windsor, it is up to you. If you like to keep using the repository pattern, just use Ninject inject them into the Service layer, like i did with the dbContext.
The best approach is to have one instance of DbContext, injecting it on each repository implementation. That way you will have a single instance of the database context, so EF will be able to detect changes on the entity objects.
If you need to use isolated dbContexts as in your example, then you need to explicitly set the state of the object as Modified.
Depending on the type of project, you should set the context on a specific scope. For example, for web applications one option is to use instance per Web request (per lifetime scope). Check this url where you can see a good explanation of the different instance scopes.
The using statement simply creates a new scope, executing the Dispose() method after the code block. EF does a lot on the background to maintain the UoW and state of the objects, but in your case, with the using, you are not using this fature.
First, a DbContext is a repository. If you want to wrap it in a custom repository, they should have the same lifecycle.
Second, your Unit-of-work is your controller. The repository should be scoped to unit-of-work.
This means that your repository needs to be Disposable, since the DbContext is.
So something like:
public interface ILoggingRepository : IDisposable
{
void LogMessage(string message);
}
// LoggingRepository.cs
public class LoggingRepository : ILoggingRepository
{
MyDbContext db;
public LoggingRepository(MyDbContext db)
{
this.db = db;
}
public void Dispose()
{
db.Dispose();
}
public void LogMessage(string message)
{
var serviceLog = new MonitoringServiceLog() { Message = message, Logged = DateTime.UtcNow };
db.MonitoringServiceLogs.Add(serviceLog);
db.SaveChanges();
}
}
If your ILoggingRepository wan't a database, it might be a file or something else that is expensive to create or open and needs to be closed.

ObjectContext Not Disposed

I'm having an issue in Entity Framework 6 where an exception is consistently thrown. For the most part the application works perfectly fine until I try adding a user to a role via a linking table.
The error being thrown is the following:
The relationship between the two objects cannot be defined because they are attached to different ObjectContext objects.
The functionality will happily add the user to the role virtually but as soon as SaveChanges() is called the process falls over.
I'm aware of the how and why for the above error and after doing some research it's due to the the context not being disposed of correctly. So following on from that and looking into the DbContext setup I've realised IDisposable wasn't added to the configuration. Unfortunately, no matter what I've tried incorporating IDisposable at any point within the application still doesn't dispose of the contexts correctly.
So after spending a fair bit of time and having no luck via Google I'm wondering if any of you have a solution or are able to point me in the right direction.
The following is a cutdown version of the Data Layer classes I've implemented:
public class GenericRepository<T> : WebsiteContext, IGenericRepository<T> where T : class
{
public virtual void Commit()
{
SaveChanges();
}
public virtual void Delete(int id)
{
var record = Set<T>().Find(id);
if (record == null)
throw new Exception("Some Message");
Set<T>().Remove(record);
}
// ... ETC
}
public interface IGenericRepository<T> where T : class
{
void Commit();
// ... ETC
}
public class WebsiteContext : DbContext, IWebsiteContext
{
static WebsiteContext()
{
Database.SetInitializer<WebsiteContext>(null);
}
public WebsiteContext() : base("Name=WebsiteContext") { }
public IDbSet<User> Users { get; set; }
// ... ETC
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// ... ETC
}
}
This implementation is loosely based around the following Stackoverflow question.
Entity Framework 6 Code First - Is Repository Implementation a Good One?
The following is a condensed version of the Service Layer class and method which is causing the issue.
private IGenericRepository<User> _userRepository;
private IGenericRepository<ApplicationUserSetting> _userSettingRepository;
private IGenericRepository<ApplicationRole> _roleRepository;
public UserManagementService()
{
_userRepository = new GenericRepository<User>();
_roleRepository = new GenericRepository<ApplicationRole>();
_userSettingRepository = new GenericRepository<ApplicationUserSetting>();
}
public void AssignUserRole(AssignRoleModel model)
{
var user = _userRepository.GetById(model.UserId);
if (user == null)
return;
var role = _roleRepository.GetById(model.RoleId);
if (role == null)
return;
user.Roles.Add(role);
_userRepository.Commit();
}
The issue, just like the error states, is because you have multiple instances of the type DbContext fetching your entities for you. Each fetched entity is then associated with the DbContext instance that retrieved it. If you want to persist changes to these entities it has to occur on the DbContext instance that it is associated with OR you have to attach it to the DbContext instance it is not associated with.
If you are trying to keep it simple I recommend you implement a DI framework like AutoFac. You can then have a single DbContext instance created per request and have it injected everywhere you need it. It will allow you to keep your existing structure (I am not going to comment on that as I consider that out of scope for this question), the end result would be that each injected GenericRepository instance has an injected WebsiteContext instance but the WebsiteContext instances are shared (all the same instance). The upside of that is no more error but the downside is you do have to be aware that any changes to any entities will result in those changes being persisted as soon as you execute the Save functionality.
Using multiple repositories causes the issue. Just use one repository (= one db context) and have different methods for getting the individual types.
E.g. _repository.Get(id)
It's way out of scope to point out how your current implementation could be made to work, but if you did want to use more than one context, you can despite what others have said.
If you do, you will have to detach the entity from the previous context first.

WPF / EntityFramework Context Lifetime

Issue
We are currently having a problem of architecture on a WPF application. It concerns EntityFramework context management, it’s instantiated once and used during the entire life of the application. So we end up with a cache issue, entities are not updated when they were loaded once. Our entities are obsolete when using the application.
Technical specification
Wpf project
.Net Framework 4 client Profile
MEF (Include in Framework 4.0 System.ComponentModel.Composition)
Design pattern MVVM
Multi users application
Architecture
This is a schema of the current architecture.
Service layer
Manage calls to business rules (business layer)
Save the context (through UnitOfWork) after business rules done
Can be called only by a ViewModel
Business layer
Define business rules
Can be called only by service layer
Repository layer
Execute methods which change context datas (insert, update , delete)
Inherit ReadOnlyRepository
Can be called only by business layer
ReadOnlyRepository layer
Execute method which return datas (select)
Can be called everywhere (ViewModel, Service layer, Business layer)
UnitOfWork
Manage context instanciation
Save context
Context available only for repositories
Code
ViewModel
[Export(typeof(OrderViewModel))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class OrderViewModel : ViewModelBase
{
private readonly IOrderManagementService _orderManagementService;
private readonly IOrderReadOnlyRepository _orderReadOnlyRepository;
[ImportingConstructor]
public OrderViewModel(IOrderManagementService orderManagementService, IOrderReadOnlyRepository orderReadOnlyRepository)
{
_orderManagementService = orderManagementService;
_orderReadOnlyRepository = orderReadOnlyRepository;
}
}
Service layer
public class OrderManagementService : IOrderManagementService
{
private readonly IUnitOfWork _unitOfWork;
private readonly IOrderManagementBusiness _orderManagementBusiness;
[ImportingConstructor]
public OrderManagementService (IUnitOfWork unitOfWork, IOrderManagementBusiness orderManagementBusiness)
{
_unitOfWork= unitOfWork;
_orderManagementBusiness = orderManagementBusiness;
}
}
Business layer
public class OrderManagementBusiness : IOrderManagementBusiness
{
private readonly IOrderReadOnlyRepository _orderReadOnlyRepository;
[ImportingConstructor]
public OrderManagementBusiness (IOrderReadOnlyRepository orderReadOnlyRepository)
{
_orderReadOnlyRepository = orderReadOnlyRepository;
}
}
ReadOnlyRepository layer
public class OrderReadOnlyRepository : ReadOnlyRepositoryBase<DataModelContainer, Order>, IOrderReadOnlyRepository
{
[ImportingConstructor]
public OrderReadOnlyRepository (IUnitOfWork uow) : base(uow)
{
}
}
ReadOnlyRepositoryBase
public abstract class ReadOnlyRepositoryBase<TContext, TEntity> : IReadOnlyRepository<TEntity>
where TEntity : class, IEntity
where TContext : DbContext
{
protected readonly TContext _context;
protected ReadOnlyRepositoryBase(IUnitOfWork uow)
{
_context = uow.Context;
}
protected DbSet<TEntity> DbSet
{
get { return _context.Set<TEntity>();
}
public virtual IEnumerable<TEntity> GetAll(System.Linq.Expressions.Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, string includeProperties = "")
{
IQueryable<TEntity> query = DbSet.AsNoTracking();
if (filter != null)
{
query = query.Where(filter);
}
foreach (var includeProperty in includeProperties.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(includeProperty);
}
if (orderBy != null)
{
return orderBy(query).ToList();
}
return query.ToList();
}
public virtual IQueryable<TEntity> All()
{
return DbSet.AsNoTracking();
}
public virtual IQueryable<TEntity> AllWhere(Expression<Func<TEntity, bool>> predicate)
{
return DbSet.Where(predicate).AsNoTracking();
}
public virtual TEntity Get(Expression<Func<TEntity, bool>> predicate)
{
return DbSet.Where(predicate).AsNoTracking().FirstOrDefault();
}
public virtual TEntity GetById(int id)
{
TEntity find = DbSet.Find(id);
_context.Entry(find).State = System.Data.EntityState.Detached;
return DbSet.Find(id);
}
We can see that the context is given to the repository in the constructor. Select methods use the "AsNoTracking ()" method to not cache entities. It's a temporary solution which is obviously not viable in long term.
UnitOfWork
public class UnitOfWork : IUnitOfWork
{
private DataModelContainer _context;
public UnitOfWork()
: this(new DataModelContainer())
{
}
public UnitOfWork(DataModelContainer context)
{
_context = context;
}
public DataModelContainer Context
{
get { return _context; }
}
public int Save()
{
return _context.SaveChanges();
}
}
During the first composition of a service with MEF, UnitOfWork will be instantiated with the default constructor which instantiate the context.
Remarks
Some pieces of code have been omitted for readability.
Goal to achieve
The lifetime of the context is clearly an issue. Knowing that all calls within the same service method must share the same context.
How can we consider modifying the architecture to avoid having a single context ?
Feel free to ask questions ! If needed, I can attach a test project which highlight the issue.
In your application there is only single unit of work but that is not the purpose of a unit a work. Instead, you need to create a unit of work each time "you work with the database". In your case the UnitOfWork should not be part of the MEF container but you can create a UnitOfWorkFactory and inject it from the container. Then the services can create a UnitOfWork each time "work has to be done" with the database:
using (var unitOfWork = unitOfWorkFactory.Create()) {
// Do work ...
unitOfWork.Save();
}
I have modified UnitOfWork so it implements IDisposable. This will allow you to dispose the EF context and also perhaps rollback a transaction if Save was not called. If you have no need for the extra transaction handling you can even get rid of the UnitOfWork class because it simply wraps the EF context and instead you can used the EF context as a unit of work directly.
This change will force you to modify how the service and the repositories are structured but you really have to because your issue is that you have a single unit of work that exists for the entire duration of the application.
Outline clearly distinguished use cases, which would maintain own lifetime scope. This could help preventing other resources leaks as well (which are pretty frequent when using WPF).
Consider generic algorithm:
Initialize lifetime scope.
Using scope:
Allocate views and other WPF resources, allocate business layer, data access (UoW, context, repo).
Load data from db and display it to user.
Wait for user action (1).
Make some changes or load even more data from DB.
Update data representation for user.
Go to (1) until scenario is complete.
Dispose scope, de-allocate resources.
The problem is that your scope currently is your application.
Now imagine that you manage scope at view level. You allocate, display view, get user's input, save changes and then the whole object tree is disposed at once.
Obviously, you should be flexible with scopes. Sometimes it can be useful to use it at view level (like "Edit item"), sometimes it could spread across several views (like wizard, for example). You can even maintain data-driven scopes (imagine you open a project in Visual Studio; begin lifetime scope to manage all resources, which should be available while project 'lives').

Using Fluent NHibernate with a Data Access Layer

First a little background: I have a solution with the following 3 projects in it:
MVC Project (User facing website)
API Project (business logic project)
Data Access Project (project where NHibernate lives)
I have the Fluent mappings in the DA layer, and (for now) I build the Hibernate SessionFactory in the GLobal.asax of the MVC site. This is not ideal as I want to have NHibernate completely contained in the DA layer and have the MVC app only communicate with the API layer. Also, I want to build the SessionFactory only once as it is an expensive operation.
To make things more complicated I have an inheritance structure like so:
User object in API layer inherits from
User data object in DA layer inherits from
Data object in DA layer.
Data object is responsible for saving the object to the database as the saving function is the same across all objects and I do not want to repeat code. The problem I am having is how do I save the User object to the database from inside the Data object class while using a SessionFactory that I instantiated when the user logged into the website and can persist through out their session.
If anything is not explained clearly please let me know.
One way to do that would be using the DI pattern, with e.g. Unity.
Implement your data object having a constructor which takes for example an IRepository interface. The implementation of this interface handles the nHibernate session factory...
Your data object could also be generic where T is one for example User data object. Then you implement a methods in data object to e.g. save, update, delete T with the injected IRepository
pseudo code for a data object
public interface IEntity
{
}
public interface IRepository
{
ISession Session { get; }
}
public class DataObjectBase<T> where T : IEntity
{
private IRepository Repository { get; set; }
public DataObjectBase(IRepository repository)
{
this.Repository = repository;
}
public T Get(int id)
{
return Repository.Session.Get<T>(id);
}
public void Save(T value)
{
Repository.Session.Save(value);
}
public void Update(T value)
{
Repository.Session.Update(value);
}
public void Delete(T value)
{
Repository.Session.Delete(value);
}
public IQueryable<T> Query()
{
return Repository.Session.Query<T>();
}
}
Implementation of your specific data object
public class ADataObject : IEntity
{
public int Id { get; set; }
// [...]
}
Implementation of your data context for the data object
public class ADataObjectContext : DataObjectBase<ADataObject>
{
public ADataObjectContext(IRepository repository)
: base(repository)
{
}
}
A simple example test using Unity
public class Test
{
public void Run()
{
IUnityContainer myContainer = new UnityContainer();
myContainer.RegisterType<IRepository, NHibernateRepository>();
var ctx = myContainer.Resolve<ADataObjectContext>();
var obj = ctx.Query().Where(p => p.Id == 2);
}
}
Of cause you would have to implement the NHibernateRespository to do whatever you want it to.
The UnityContainer initialization should be done within your global.asax within the MVC project. You can also configure Unity via web.config.
The NHibernateRespository should actually be a singleton. This can either be implemented by you, or you simply use the Unity functionality to instantiate your type as singleton. The new ContainerControlledLifetimeManager() does exactly that.
Instead of exposing the session as a property you can of cause expose a method which opens a new session. Or you implement a Begin and End unit of work, which is common practice in web environments...
Other links for a normal repository pattern, and unit of work, unity... or simply search on Google for nhibernate repository pattern
http://slynetblog.blogspot.de/2011/11/in-spite-of-common-now-approach-of.html
http://blog.bobcravens.com/2010/07/using-nhibernate-in-asp-net-mvc/
http://msdn.microsoft.com/en-us/library/dd203101.aspx
You can use this options:
Using AOP: when a function is called in API layer, AOP creates a session and passes the value parameters in methods or constructors to DA layer.
From MVC project to DA layer, it passes a session to DA layer with parameters in method o constructors, through all the layers.
Thinks the session is always associated with the interface layer.

Categories