我正在使用业务对象(员工、产品)创建一个新项目。由于限制,我没有使用 LINQ to SQL 或任何 ORM 映射器。
我必须手动编写数据访问层代码。我有兴趣使用“存储库模式”。
根据我的理解,我必须创建一个通用存储库 IRepository
,它由所有存储库 ProductRepository、EmployeeRepository
实现。
让我困惑的是不同的业务对象有不同的需求。例如:
产品库
GetAllProducts ();
GetProductById (int id);
GetProductByMaxPrice (double price);
GetProductByNamePrice (string name, double Price);
Get... (...);
员工资料库
GetEmployeeByAge ();
GetEmployeeByJob (string description);
GetEmployeeBySalary (double salary);
Get... (...); //and so on
如何创建满足不同对象的不同数据访问要求的通用存储库?
我已经阅读了很多关于 Repository Pattern 的理论,但非常希望能有一个有效的例子。
此外,如果我可以使用通用存储库创建所有存储库,那么使用工厂模式也会变得容易。例如:
interface IRepository
{
....
}
ProductRepository : IRepository
{
....
}
EmployeeRepository : IRepository
{
....
}
然后我们可以有效地使用工厂模式:
IRepository repository;
repository = new ProductRepository ();
repository.Call_Product_Methods ();
repository = new EmployeeRepository ();
repository.Call_Employee_Methods ();
最佳答案
repository Pattern 是一个很好用的模式,但如果没有正确使用它,不但不会让你的生活更轻松,反而会带来巨大的痛苦!
因此,执行此操作的最佳方法(因为您不想使用 EF 或其他 ORM)是创建通用接口(interface),然后创建基本抽象实现。这样您就不需要为每个存储库编写代码,您只需按类型实例化它们即可!
在此之后,如果您有特定于某些实体的任何特定方法,您都可以从存储库继承并根据需要覆盖或添加方法和属性。
如果你想使用 Repository Pattern,我也建议你使用 IUnitOfWork 模式,并将它与 repository 分开。
两个界面应该是这样的:
非常简单的 IUnitOfWork:
Public interface IUnitOfWork
{
bool Save();
}
还有他们,Repository 接口(interface),使用泛型:
public interface IRepository<TEntity> : IDisposable where TEntity : class
IUnitOfWork Session { get;}
IList<TEntity> GetAll();
IList<TEntity> GetAll(string[] include);
IList<TEntity> GetAll(Expression<Func<TEntity, bool>> predicate);
bool Add(TEntity entity);
bool Delete(TEntity entity);
bool Update(TEntity entity);
bool IsValid(TEntity entity);
}
方法 .Add()、.Delete() 不应将任何内容发送到数据库,但它们应始终将更改发送到 IUnitOfWork(您可以在 DAL 类中实现),并且仅当您调用 . IUnitOfWork 的 Save() 方法,您会将内容保存到数据库。
我已经使用 EntityFramework 实现了我的 Repository 类,这使事情变得更容易,但您可以按照自己的方式进行。
您将使用的代码如下所示:
void SomeMethod()
{
using (IUnitOfWork session = new YourUnitOfWorkImplementation())
{
using (var rep = new Repository<Client>(session))
{
var client1 = new Client("Bob");
var client2 = new Cliente("John");
rep.Add(client1);
rep.Add(client2);
var clientToDelete = rep.GetAll(c=> c.Name == "Frank").FirstOrDefaut();
rep.Delete(clientToDelete);
//Now persist the changes to the database
session.Save();
{
{
}
就像我说的,有了 EF 和 DbContext,这就容易多了,下面是我的 Repository 类的一小部分:
public class Repository : Component, IRepository
{
protected DbContext session;
{
get
{
if (session == null)
throw new InvalidOperationException("A session IUnitOfWork do repositório não está instanciada.");
return (session as IUnitOfWork);
}
}
public virtual DbContext Context
{
get
{
return session;
}
}
public Repository()
: base()
{
}
public Repository(DbContext instance)
: this(instance as IUnitOfWork)
{
#endregion
public IList<TEntity> GetAll<TEntity>() where TEntity : class
{
return session.Set<TEntity>().ToList();
}
public bool Add<TEntity>(TEntity entity) where TEntity : class
{
if (!IsValid(entity))
return false;
try
{
session.Set(typeof(TEntity)).Add(entity);
return session.Entry(entity).GetValidationResult().IsValid;
}
catch (Exception ex)
{
if (ex.InnerException != null)
throw new Exception(ex.InnerException.Message, ex);
throw new Exception(ex.Message, ex);
}
} ...
这样您就不需要构建 GetEmployeeByAge,您只需编写:
IEnumerable<Employee> GetEmployee(int age)
{
return rep.GetAll<Employee>(e=> e.Age == age);
}
或者你可以直接调用(不需要创建方法)
关于c# - 具有数据访问层的通用存储库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16572743/