c# - 具有数据访问层的通用存储库

标签 c# oop design-patterns

我正在使用业务对象(员工、产品)创建一个新项目。由于限制,我没有使用 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/

相关文章:

c# - 抽象类中的可选参数覆盖派生

C# 正在自行舍入除法

c# - 有人可以澄清 Entity Framework 和类型化数据集之间的主要区别吗?

函数中的 C++ 函数?

c# - 命令模式用于返回数据

c# - 如何查询 Kendo MVVM Treeview 模型

c# - 默认方法是 "virtual"还是 "not virtual"? :

c# - 如何处理 OO 应用程序中的横切关注点?使用单例?依赖注入(inject)?什么?

c++ - 寻找更好的C++类工厂

design-patterns - 层次结构和设计模式问题