我正在使用NHibernate在ASP.NET MVC中开发一个Web应用程序。
根据我在Google上发现的文章和教程,我正在为我的课程使用Repository。
我有10个类和10个存储库。今天我发现除了班级以外,90%的矿藏都是完全相同的。这是一个例子:
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);
}
}
有一种方法可以做一种我可以在我所有课程中使用的通用存储库吗?
如果可能的话,如果我需要为特定类创建特定方法,我该怎么办?
答案 0 :(得分:6)
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);
}
}
答案 1 :(得分:4)
您应该创建一个通用存储库,您可以在一般情况下使用它,如果特定类需要任何额外的方法,请使用继承添加它。使用您的示例:
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 */ }
}
答案 2 :(得分:3)
以下是我对类似问题的回答(截至目前为28票):
Advantage of creating a generic repository vs. specific repository for each object?
这个想法是将实现泛化,而不是接口。而不是向外的通用存储库接口,创建一个面向内部的通用存储库基类,您可以使用它来轻松实现特定于实体的接口。
编辑:我应该指出,通用存储库提供的非常不同的功能比特定的存储库。存储库旨在封装实体查询背后的数据访问机制,包括所有查询逻辑。通用存储库封装了创建查询的能力,但它没有封装任何关于实体的特定查询。
关键是不要让存储库消费者负责编写自己的查询。通用存储库与ORM处于相同的抽象级别;特定的存储库位于该级别之上。
答案 3 :(得分:2)
看看我对“Asp.net MVC 2 Entity Framework Generic Repository Method. how to Update a specific Collumn”问题的回答 - 它应该让你知道该怎么做。
HTHS, 查尔斯
E.g。
基础模型:
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; }
}
你的模特
public class Category : DbTable
{
public string Name { get; set; }
}
您的存储库
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);
}
}
哦,不要忘记具体的实现
public interface ICategoryRepository : IBaseRepository<Category>
{
Category GetCategoryByName(string categoryName);
}
public CategoryRepository : BaseRepository<Category>
{
public Category GetCategoryByName(string categoryName)
{
//blah
}
}
答案 4 :(得分:2)