I'm using MVC pattern in my application. For each model class I have a controller one. All controller classes have a saveOrUpdate() method. I am wondering if this is enough to create an Interface which defines said method, and then all controller implements it.
Please note that saveOrUpdate() receive a model class as a parameter. So it would be something like UserController#saveOrUpdate(User user), CourseController#saveOrUpdate(Course course), AppleManager#saveOrUpdate(Apple apple).
I think what you need is generic repository which implements generic functionality for a given entity. I've recently started implementing Repository Pattern along with Unit of Work in my MVC projects. Here is how I do that.
MyDbContext.cs:
public class MyDbContext : DbContext
{
public MyDbContext() : base("name=DefaultConnection”)
{
}
public System.Data.Entity.DbSet<User> Users { get; set; }
public System.Data.Entity.DbSet<Course> Courses { get; set; }
}
Unit of Work:
public class UnitOfWork : IUnitOfWork
{
//private variable for db context
private MyDbContext _context;
//initial db context variable when Unit of Work is constructed
public UnitOfWork()
{
_context = new MyDbContext();
}
//property to get db context
public MyDbContext Context
{
//if not null return current instance of db context else return new
get { return _context ?? (_context = new MyDbContext()); }
}
//save function to save changes using UnitOfWork
public void Save()
{
_context.SaveChanges();
}
}
Generic Repository:
public class RepositoryBase<T> : IRepositoryBase<T> where T : class
{
protected readonly IUnitOfWork _unitOfWork;
private readonly IDbSet<T> _dbSet;
public RepositoryBase(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
_dbSet = _unitOfWork.Context.Set<T>();
}
public virtual void Save()
{
_unitOfWork.Save();
}
public virtual void Add(T entity)
{
_dbSet.Add(entity);
_unitOfWork.Save();
}
//Similarly you can have Update(), Delete(), GetAll() implementation here
}
Entity Repository inheriting from generic repo:
public class UserRepository:RepositoryBase<User>,IUserRepository
{
public UserRepository(IUnitOfWork unitOfWork) : base(unitOfWork)
{
}
//Here you can also define functions specific to User
}
Controller:
public class UserController : Controller
{
private readonly IUserRepository _dbUserRepository;
public UserController(IUserRepository dbUserRepository)
{
_dbUserRepository = dbUserRepository;
}
// GET: /User/
public ActionResult Index()
{
var users = _dbUserRepository.GetAll();
return View(users.ToList());
}
}
create an interface
interface ISave
{
void Save(object obj);
}
now in your controller implement it.
public class AppleControler : Controller , ISave
{
public void Save(Object obj)
{
//you can cast your object here.
}
}
Option two
interface ISave<T>
{
void Save(T obj);
}
public class AppleControler : Controller , ISave<Apple>
{
public void Save(Apple obj)
{
}
}
Related
I Have a PhoneBook Project in MVC and use IUnitOfWork .
but I dont Know that How do this project.
the link of the project :
http://www.mediafire.com/download/jy0b5ins5eisy5t/MvcAppPhoneBook.rar
please complate thie project for me
i'm doing CRUD in this project.
I've used generic repo and UoW in my projects as below. You can take reference of this to complete your project. I usually have 4 layer solution architecture:
Core
Model classes
Data
Generic Repo and UoW
DbContext
Code first migrations
Web
applications solution with dependency injection implementation (e.g.Ninject)
Test
Model classes
public class User
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Course
{
public int Id { get; set; }
public string Name { get; set; }
}
MyDbContext.cs:
public class MyDbContext : DbContext
{
public MyDbContext() : base("name=DefaultConnection”)
{
}
public System.Data.Entity.DbSet<User> Users { get; set; }
public System.Data.Entity.DbSet<Course> Courses { get; set; }
}
Unit of Work:
public class UnitOfWork : IUnitOfWork
{
//private variable for db context
private MyDbContext _context;
//initial db context variable when Unit of Work is constructed
public UnitOfWork()
{
_context = new MyDbContext();
}
//property to get db context
public MyDbContext Context
{
//if not null return current instance of db context else return new
get { return _context ?? (_context = new MyDbContext()); }
}
//save function to save changes using UnitOfWork
public void Save()
{
_context.SaveChanges();
}
}
Generic Repository:
public class RepositoryBase<T> : IRepositoryBase<T> where T : class
{
protected readonly IUnitOfWork _unitOfWork;
private readonly IDbSet<T> _dbSet;
public RepositoryBase(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
_dbSet = _unitOfWork.Context.Set<T>();
}
public virtual void Save()
{
_unitOfWork.Save();
}
public virtual void Add(T entity)
{
_dbSet.Add(entity);
_unitOfWork.Save();
}
//Similarly you can have Update(), Delete(), GetAll() implementation here
}
Entity Repository inheriting from generic repo:
public class UserRepository:RepositoryBase<User>,IUserRepository
{
public UserRepository(IUnitOfWork unitOfWork) : base(unitOfWork)
{
}
//Here you can also define functions specific to User
}
controller.cs
public class UserController : Controller
{
private readonly IUserRepository _dbUserRepository;
public UserController(IUserRepository dbUserRepository)
{
_dbUserRepository = dbUserRepository;
}
// GET: /User/
public ActionResult Index()
{
var users = _dbUserRepository.GetAll();
return View(users.ToList());
}
//Other CRUD operations
}
Here is my project responsible for data:
public interface IRepository<T> where T : class
{
IQueryable<T> All();
T GetById(int id);
void Add(T entity);
void Update(T entity);
....
}
EF implement IRepository
public class GenericRepository<T> : IRepository<T> where T : class
{
public GenericRepository() : this(new ApplicationDbContext())
{
}
public GenericRepository(DbContext context)
{
if (context == null)
{
throw new ArgumentException("An instance of DbContext is required to use this repository.", "context");
}
this.Context = context;
this.DbSet = this.Context.Set<T>();
}
protected IDbSet<T> DbSet { get; set; }
protected DbContext Context { get; set; }
public virtual IQueryable<T> All()
{
return this.DbSet.AsQueryable();
}
public virtual T GetById(int id)
{
return this.DbSet.Find(id);
}........
I use unit of work pattern
public interface IUowData : IDisposable
{
IRepository<House> Houses { get; }
IRepository<Floor> Floors { get; }
...
int SaveChanges();
}
And this is his implementation
public class UowData:IUowData
{
private readonly DbContext context;
private readonly Dictionary<Type, object> repositories = new Dictionary<Type, object>();
public UowData(){}
public UowData(DbContext context)
{
this.context = context;
}
private IRepository<T> GetRepository<T>() where T : class
{
if (!this.repositories.ContainsKey(typeof(T)))
{
var type = typeof(GenericRepository<T>);
this.repositories.Add(typeof(T), Activator.CreateInstance(type, this.context));
}
return (IRepository<T>)this.repositories[typeof(T)];
}
public int SaveChanges()
{
return this.context.SaveChanges();
}
public void Dispose()
{
this.context.Dispose();
}
The second project is of type Web API through which I try to access data from database:
public class ArduinoController : ApiController
{
private IEmailSender sender;
private IUowData data;
public ArduinoController(IEmailSender sender, IUowData data)
{
this.sender = sender;
this.data = data;
}
[HttpPost]
[ActionName("PostAlarm")]
public void PostAlarm(dynamic sensorJson)
{
var alartModel = this.data.Sensors.All()
.....
When I try to use Ninject dependancy resolve i get exception:
"The context cannot be used while the model is being created. This exception may be thrown if the context is used inside the OnModelCreating method or if the same context instance is accessed by multiple threads concurrently. Note that instance members of DbContext and related classes are not guaranteed to be thread safe.".
Everything works fine if I fetch one page at a time. I am using a simple tool 'XENU' to fetch multiple pages simultaneously. This is when I get errors with DBContext by fetching multiple pages at a time.
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
public static void Stop()
{
bootstrapper.ShutDown();
}
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver = new Ninject.WebApi.DependencyResolver.NinjectDependencyResolver(kernel);
return kernel;
}
private static void RegisterServices(IKernel kernel)
{
EmailSettings emailSettings = new EmailSettings
{
ServerName = Settings.Default.EmailServerName,
...
};
kernel.Bind<IEmailSender>().To<EmailSender>().WithConstructorArgument("settings", emailSettings);
kernel.Bind<IUowData>().To<UowData>().InRequestScope().WithConstructorArgument("context",new ApplicationDbContext());
}
}
.WithConstructorArgument("context",new ApplicationDbContext());
results in one DB Context for the whole application. Remove that and add a binding instead.
.Bind<DbContext>().To<ApplicationDbContext>().InRequestScope();
Lets say I have 2 tables. ProductCategory and Product. I have 1 generic repository that can handle both tables:
public class GenericRepository<T> : IRepository<T>
But when using unit of work pattern, am I forced to create a repository for ALL tables in my database?
public interface IUnitOfWork : IDisposable
{
int SaveChanges();
IRepository<ProductCategory> ProductCategoryRepository { get; }
IRepository<Product> ProductRepository { get; }
}
Is there not a way I can add the generic repository to the unit of work class?
You can add a generic method to the IUnitOfWork interface:
public interface IUnitOfWork : IDisposable
{
int SaveChanges();
IRepository<T> Repository<T>();
}
But i don't recommend it. It's smells like Service Locator anti-pattern and SRP violation. Better way is to remove all repositories from the IUnitOfWork interface, because providing access to repository is not UnitOfWork's responsibility. I recommend to separate repository from UnitOfWork and inject their into the consumer by itself.
public class Consumer
{
private readonly IUnitOfWork _unitOfWork;
private readonly IRepository<Product> _products;
public Consumer(IUnitOfWork unitOfWork, IRepository<Product> products)
{
_unitOfWork = unitOfWork;
_products = products;
}
public void Action()
{
var product = _products.GetOne();
product.Name = "new name";
_products.Update(product);
_unitOfWork.SaveChanges();
}
}
UDATE:
UnitOfWork and Repository can share context instance.
Here the sample of code:
public class EfUnitOfWork : IUnitOfWork
{
private readonly DbContext _context;
public EfUnitOfWork(DbContext context)
{
_context = context;
}
public void SaveChanges()
{
_context.SaveChanges();
}
}
public class EfRepository<T> : IRepository<T> where T : class
{
private readonly DbContext _context;
public EfRepository(DbContext context)
{
_context = context;
}
//... repository methods...
}
public class Program
{
public static void Main()
{
//poor man's dependency injection
var connectionString = "northwind";
var context = new DbContext(connectionString);
var unitOfWork = new EfUnitOfWork(context);
var repository = new EfRepository<Product>(context);
var consumer = new Consumer(unitOfWork, repository);
consumer.Action();
}
}
Demonstrating a solution with only one class would be
public class Session : ISession
{
private readonly DbContext _dbContext;
public Session(DbContext dbContext)
{
_dbContext = dbContext;
}
public TEntity Single<TEntity>(Expression<Func<TEntity, bool>> expression) where TEntity : class
{
return _dbContext.Set<TEntity>().SingleOrDefault(expression);
}
public IQueryable<TEntity> Query<TEntity>() where TEntity : class
{
return _dbContext.Set<TEntity>().AsQueryable();
}
public void Commit()
{
try { _dbContext.SaveChanges(); }
catch (DbEntityValidationException ex)
{
var m = ex.ToFriendlyMessage();
throw new DbEntityValidationException(m);
}
}
public void Dispose()
{
_dbContext.Dispose();
}
public void Add<TEntity>(IEnumerable<TEntity> items) where TEntity : class
{
items.ToList().ForEach(Add);
}
public void Add<TEntity>(TEntity item) where TEntity : class
{
_dbContext.Set<TEntity>().Add(item);
}
public void Remove<TEntity>(TEntity item) where TEntity : class
{
_dbContext.Set<TEntity>().Remove(item);
}
public void Remove<TEntity>(Expression<Func<TEntity, bool>> expression) where TEntity : class
{
var items = Query<TEntity>().Where(expression);
Remove<TEntity>(items);
}
public void Remove<TEntity>(IEnumerable<TEntity> items) where TEntity : class
{
items.ToList().ForEach(Remove);
}
}
and then your usage can be
public class User
{
public int? Id { get; set; }
public string Name { get; set; }
public DateTime Dob { get; set; }
}
public class Usage
{
private readonly ISession _session;
public Usage(ISession session) { _session = session; }
public void Create(User user)
{
_session.Add(user);
_session.Commit();
}
public void Update(User user)
{
var existing = _session.Single<User>(x => x.Id == user.Id);
// this gets cumbursome for an entity with many properties.
// I would use some thing like valueinjecter (nuget package)
// to inject the existing customer values into the one retreived from the Db.
existing.Name = user.Name;
existing.Dob = user.Dob;
_session.Commit();
}
}
I have deliberately not included a Repository class. To have a class encapsulate both queries and commands for every entity is an over kill and a needless abstraction. Its almost a design flaw at a fundamental level. Queries and commands are fundamentally different concerns. Queries in the most simplest manner can be created as extensions methods on the ISession interface. Commands can be done using a few classes like such..
public interface ICommand<in TSource>
{
void ApplyTo(TSource source);
}
public interface ICommandHandler<out TSource>
{
void Handle(ICommand<TSource> command);
}
public class LinqCommandHandler : ICommandHandler<IStore>
{
private readonly ISession _session;
public LinqCommandHandler(ISession session)
{
_session = session;
}
public void Handle(ICommand<IStore> command)
{
command.ApplyTo(_session);
_session.Commit();
}
}
public class UpdateDobForUserName : ICommand<IStore>
{
public string UserName { get; set; }
public DateTime Dob { get; set; }
public void OnSend(IStore store)
{
var existing = store.Query<User>().SingleOrDefault(x => x.Name == UserName);
existing.Dob = Dob;
}
}
public class Usage
{
private readonly ICommandHandler<IStore> _commandHandler;
public Usage(ICommandHandler<IStore> commandHandler)
{
_commandHandler = commandHandler;
}
public void Update()
{
var command = new UpdateDobForUserName {UserName = "mary", Dob = new DateTime(1960, 10, 2)};
_commandHandler.Handle(command);
}
}
The IStore above is the same as the Session class, except that it doesn't implement the IDisposable interface and doesn't have a Commit() method. The ISession then obviously inherits from an IStore and also implements IDisposable and has one method Commit(). This ensures an ICommand<IStore> can never open or dispose connections and cannot commit. Its responsibility is to define a command and define how its applied. Who applies it and what happens and what not on command application is a different responsibility which is with the ICommandHandler<IStore>.
There are many ways to implement Unit of work. I prefer having the repositories take a Unit of Work in its constructor (which is passed via Dependency Injection), then you only create repositories for your needs.
My question is very similar to this one: MVC3 tool using Entity Framework caching issues with Ninject however my mapping is a bit more complex and when I use InRequestScope I get the following error:
The operation cannot be completed because the DbContext has been disposed.
If I don't include InRequestScope everything works except EF Code First seems to cache my entities and it doesn't match up to the values in the Db.
Here's my ninject mapping I'm using the ninject mvc3 nuget package (without InRequestScope):
kernel.Bind<MyContext>()
.ToSelf()
.WithConstructorArgument("connectionString", context => MvcApplication.GetConnectionStringName);
kernel.Bind<IUnitOfWork>().To<UnitOfWork>();
// Service Layer.
kernel.Bind<ICustomerService>().To<CustomerService>();
kernel.Bind<IMessageService>().To<MessageService>();
kernel.Bind<IUserService>().To<UserService>();
// Repository Layer.
kernel.Bind<IRepository<Customer>>().To<GenericRepository<Customer>>();
kernel.Bind<IRepository<Message>>().To<GenericRepository<Message>>();
kernel.Bind<IRepository<User>>().To<GenericRepository<User>>();
NinjectContainer.Initialize(kernel);
My IUnitOfWork
public interface IUnitOfWork
{
IUserService UserService { get; }
ICustomerService CustomerService { get; }
IMessageService MessageService { get; }
void CommitChanges();
}
My UnitOfWork
public class UnitOfWork : IUnitOfWork
{
MyContext _context;
private readonly IUserService _userService;
private readonly ICustomerService _customerService;
private IMessageService _messageService;
public UnitOfWork(IUserService userService,
ICustomerService customerService,
IMessageService messageService,
MyContext context)
{
_userService = userService;
_customerService = customerService;
_messageService = messageService;
SetContext(optimaContext);
}
private void SetContext(MyContext context)
{
_context = context;
_userService.Context = _context;
_customerService.Context = _context;
_messageService.Context = _context;
}
public void CommitChanges()
{
_context.SaveChanges();
}
public IUserService UserService { get { return _userService; } }
public ICustomerService CustomerService { get { return _customerService; } }
public IMessageService MessageService { get { return _messageService; } }
}
My ICustomerService
public interface ICustomerService
{
DbContext Context { get; set; }
IQueryable<Customer> All();
}
My CustomerService
public class CustomerService : ICustomerService
{
IRepository<Customer> _customerRepo;
public CustomerService(IRepository<Customer> customerRepo)
{
_customerRepo = customerRepo;
}
private DbContext _context;
public DbContext Context
{
get { return _context; }
set { _context = value; _customerRepo.Context = value; }
}
public IQueryable<Customer> All()
{
return _customerRepo.All();
}
}
My other services follow a similar patter.
My IRepository
public interface IRepository<T> where T : class, new()
{
DbContext Context { get; set; }
T Single(Expression<Func<T, bool>> expression);
T Find(object id);
IQueryable<T> All();
void Delete(Expression<Func<T, bool>> expression);
void Delete(T item);
}
My Repository
public class GenericRepository<T> : IRepository<T> where T : class, new()
{
DbContext _context;
public DbContext Context
{
get { return _context; }
set { _context = value; }
}
public virtual T Single(Expression<Func<T, bool>> expression)
{
return All().FirstOrDefault(expression);
}
public virtual T Find(object id)
{
return _context.Set<T>().Find(id);
}
public virtual IQueryable<T> All()
{
return _context.Set<T>();
}
public virtual void Delete(Expression<Func<T, bool>> expression)
{
var items = All().Where(expression);
foreach (var item in items)
{
Delete(item);
}
}
public virtual void Delete(T item)
{
_context.Set<T>().Remove(item);
}
}
If anyone can help with the Ninject mapping and the correct way to inject classes it would be greatly appreciated.
I found the problem, I was using the [Inject] attribute with a FilterAttribute when the attribute was being called it was before my context had been initialised and that producted the dbContext error.
I followed the wiki on the ninject github site here to setup ninject on FilterAttribute. On issue I did have was finding the BindFilter method, this is hidden away Ninject.Web.Mvc.FilterBindingSyntax namespace.
My ninject mappings now look like:
kernel.Bind<MyContext>()
.ToSelf()
.InRequestScope()
.WithConstructorArgument("connectionString", context => MvcApplication.GetConnectionStringName);
kernel.Bind<IUnitOfWork>().To<UnitOfWork>();
// Service Layer.
kernel.Bind<ICustomerService>().To<CustomerService>();
kernel.Bind<IMessageService>().To<MessageService>();
kernel.Bind<IUserService>().To<UserService>();
// Repository Layer.
kernel.Bind<IRepository<Customer>>().To<GenericRepository<Customer>>();
kernel.Bind<IRepository<Message>>().To<GenericRepository<Message>>();
kernel.Bind<IRepository<User>>().To<GenericRepository<User>>();
// Attributes
kernel.BindFilter<AuthorizeWithTokenAttribute>(FilterScope.Controller, 0)
.WhenControllerHas<AuthorizeWithTokenFilter>()
.WithConstructorArgumentFromControllerAttribute<AuthorizeWithTokenFilter>("roles", attribute => attribute.Roles)
.WithConstructorArgumentFromControllerAttribute<AuthorizeWithTokenFilter>("users", attribute => attribute.Users);
I'm developing a web application in ASP.NET MVC with NHibernate.
Based in articles and tutorials I've found at Google, I'm using Repository for my classes.
I have 10 classes and 10 repositories. Today I figured out that 90% of mine repositories are exactly equal each other, except for the class. This is one example:
public class PromocaoRepository:IPromocaoRepository {
private ISession Session;
public PromocaoRepository() {
this.Session = NHibernateSessionFactory.OpenSession();
}
public void Add(Promocao promocao) {
using(ITransaction transaction = this.Session.BeginTransaction()) {
this.Session.Save(promocao);
transaction.Commit();
}
}
public void Edit(Promocao promocao) {
using(ITransaction transaction = this.Session.BeginTransaction()) {
this.Session.Update(promocao);
transaction.Commit();
}
}
public void Remove(Promocao promocao) {
using(ITransaction transaction = this.Session.BeginTransaction()) {
this.Session.Delete(promocao);
transaction.Commit();
}
}
public Promocao GetById(int id) {
return this.Session.Get<Promocao>(id);
}
}
There is a way to do a kind of generic repository witch I can use in all my classes?
If it's possible, what should I do in case I need to create a particular method for an specific class?
From another thread:
public interface IRepository<T> : IQueryable<T>
{
void Add(T entity);
T Get(Guid id);
void Remove(T entity);
}
public class Repository<T> : IQueryable<T>
{
private readonly ISession session;
public Repository(ISession session)
{
session = session;
}
public Type ElementType
{
get { return session.Query<T>().ElementType; }
}
public Expression Expression
{
get { return session.Query<T>().Expression; }
}
public IQueryProvider Provider
{
get { return session.Query<T>().Provider; }
}
public void Add(T entity)
{
session.Save(entity);
}
public T Get(Guid id)
{
return session.Get<T>(id);
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
public IEnumerator<T> GetEnumerator()
{
return session.Query<T>().GetEnumerator();
}
public void Remove(T entity)
{
session.Delete(entity);
}
}
Wrapping up nHibernate in repositories
That being said, you should take a look at S#arp Architecture, which already helps you with this repetitive process using Dependency Injection.
You should make a generic repository, which you can use in the general case, and if any extra methods is needed for a particular class, add it by using inheritance. Using your example:
public class GenericRepository<TEntity> :IGenericRepository<TEntity> {
private ISession Session;
public GenericRepository() {
this.Session = NHibernateSessionFactory.OpenSession();
}
public void Add(TEntity instance) {
using(ITransaction transaction = this.Session.BeginTransaction()) {
this.Session.Save(instance);
transaction.Commit();
}
}
/* other methods */
}
public class SpecificRepository : GenericRepository<SpecificEntity>, ISpecificRepository
{
public void SpecialQuery() { /* added method implementation */ }
}
Here is my answer to a similar question (28 votes as of right now):
Advantage of creating a generic repository vs. specific repository for each object?
The idea is to genericize the implementation, not the interface. Instead of an outward-facing generic repository interface, create an inward-facing generic repository base class, which you use to easily implement entity-specific interfaces.
Edit: I should point out that generic repositories serve a very different function than specific repositories. Repositories are intended to encapsulate the data access mechanisms behind the entity's queries, including all of the query logic. A generic repository encapsulates the ability to create queries, but it doesn't encapsulate any specific query about an entity.
The point is to not make repository consumers responsible for writing their own queries. A generic repository lives at the same level of abstraction as an ORM; a specific repository lives at a level above that.
Here's another example of a generic repository
Have a look at my answer to the question "Asp.net MVC 2 Entity Framework Generic Repository Method. how to Update a specific Collumn" - it should give you a good idea of what to do.
HTHs,
Charles
E.g.
Base model:
public interface IDbTable
{
int Id { get; set; }
DateTime DateCreated { get; set; }
DateTime DateUpdated { get; set; }
}
public class DbTable
{
public int Id { get; set; }
public DateTime DateCreated { get; set; }
public DateTime DateUpdated { get; set; }
}
Your model
public class Category : DbTable
{
public string Name { get; set; }
}
Your repository
public interface IBaseRepository<T> where T : class, IDbTable
{
void Add<T>(T entity);
void Edit<T>(T entity);
void Remove<T>(T entity);
T GetById(int id);
}
public class BaseRepository<T> : IBaseRepository<T>
{
private ISession Session;
public BaseRepository()
{
this.Session = NHibernateSessionFactory.OpenSession();
}
public void Add(T entity)
{
entity.DateCreated = DateTime.UtcNow;
entity.DateUpdated = DateTime.UtcNow;
using(ITransaction transaction = this.Session.BeginTransaction())
{
this.Session.Save(entity);
transaction.Commit();
}
}
public void Edit(T entity)
{
entity.DateUpdated = DateTime.UtcNow;
using(ITransaction transaction = this.Session.BeginTransaction())
{
this.Session.Update(entity);
transaction.Commit();
}
}
public void Remove(T entity)
{
using(ITransaction transaction = this.Session.BeginTransaction())
{
this.Session.Delete(entity);
transaction.Commit();
}
}
public T GetById(int id)
{
return this.Session.Get<T>(id);
}
}
Oh, and lets not forget the concrete implementation
public interface ICategoryRepository : IBaseRepository<Category>
{
Category GetCategoryByName(string categoryName);
}
public CategoryRepository : BaseRepository<Category>
{
public Category GetCategoryByName(string categoryName)
{
//blah
}
}