繁体   English   中英

这种设计模式是否有名称,其中具体类实现了一个特定接口,该接口实现了 CRUD 操作的基本接口?

[英]Is there a name for this design pattern where a concrete class implements a specific interface which implements a base interface for CRUD operations?

我试图把它变成一个“通用”问题,因为我在 Java 和 C# 中看到过这个问题,我假设它也在其他 OO 语言中。

我知道访问数据并执行CRUD操作的应用程序有三个“主要”框架:

有时这些设计模式使用DAO ,有时使用DTO

在查看使用这三种设计模式之一的应用程序的教程和示例时,大多数(如果不是全部)执行以下操作:

BaseRepositoryInterface (我有时将其视为接口,有时将其视为抽象类)

interface BaseRepositoryInterface {

    findOne(integer id);

    findAll();

    create();

    read(integer id);

    update(integer id);

    delete(integer id);
}

特定存储库接口

interface SpecificRepositoryInterface implements BaseRepositoryInterface {

    // Just Some Examples
    specificActionNumberOne(integer id, String someString);

    specificActionNumberTwo(integer id, Object someObject);

    specificActionNumberThree(integer id, double someDouble);
}

具体存储库类

class ConcreteRepositoryClass implements SpecificRepositoryInterface {

    Dao myDao;
    // or
    Dto myDto;

    ConcreteRepositoryClass(Dao someDao)
    // or 
    ConcreteRepositoryClass(Dto someDto)
    {
        this.myDao = someDao;
        // or
        this.myDto = someDto;
    }

    findOne(integer id){
        // implement here ...
    }

    findAll(){
        // implement here ...
    }

    create(){
        // implement here ...
    }

    read(integer id){
        // implement here ...
    }

    update(integer id){
        // implement here ...
    }

    delete(integer id){
        // implement here ...
    }

    specificActionNumberOne(integer id, String someString){
        // implement here ...
    }

    specificActionNumberTwo(integer id, Object someObject){
        // implement here ...
    }

    specificActionNumberThree(integer id, double someDouble){
        // implement here ...
    }
}

这在所有示例中并不总是完全相同,但它们都倾向于遵循相同的格式。

鉴于此,这种设计模式有名字吗?

假设我正在寻找名称的这种模式是上述框架的“演示者”、“控制器”或“视图模型”部分,只是进一步抽象,是否安全?

对我来说,这是存储库模式 在大多数情况下,这是在模型后面或连接到模型。 从存储库中,您可以为您提到的所有这些模式提供数据以进行建模。 模型可以直接存储在存储库中,也可以转换为一些 DTO 后存储。 存储库通常由接口表示,以便在没有真正连接到持久层的情况下进行测试。

我们有一个通用存储库模式,也有一个特定的存储库模式。 两者都是正确的,各有利弊。

用于在 C# 中实现存储库模式:

public interface ICustomerRepository 
{        
    IEnumerable GetCustomers();        
    Customer GetCustomerByID(int customerId);        
    void InsertCustomer(Customer customer);        
    void DeleteCustomer(int customerId);        
    void UpdateCustomer(Customer customer);        
    void Save();    
}

上述接口与 EF 的实现如下所示:

public class CustomerRepository:ICustomerRepository    
{        
    private ApplicationContext context;        
 
    public CustomerRepository(ApplicationContext context)        
    {            
        this.context = context;        
    }        
    
    public IEnumerable<Customer> GetCustomers()        
    {            
        return context.Customers.ToList();        
    }        
    public Customer GetCustomerByID(int customerId)        
    {
        return context.Customers.Find(customerId);
    }
    
    public void InsertCustomer(Customer customer)
    {            
        context.Customers.Add(customer);      
    }        
    
    public void DeleteCustomer(int customerId)        
    {            
        Customer customer = context.Customers.Find(customerId);                    
        context.Customers.Remove(customer);        
    }        
    
    public void UpdateCustomer(Customer customer)        
    {            
        context.Entry(customer).State = EntityState.Modified;        
    }        
    
    public void Save()        
    {            
        context.SaveChanges();        
    }
    
}

就是这样!

现在在 C# 中实现通用存储库模式

首先,为通用存储库创建一个接口

public interface IRepository<TEntity> where TEntity :class
{
    void Delete(TEntity entityToDelete);
    void Delete(object id);
    IEnumerable<TEntity> Get(
        Expression<Func<TEntity, bool>> filter = null, 
        Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, 
        string includeProperties = "");
    TEntity GetByID(object id);
    IEnumerable<TEntity> GetWithRawSql(string query, 
        params object[] parameters);
    void Insert(TEntity entity);
    void Update(TEntity entityToUpdate);
}

然后上述接口与 EF 的实现如下所示:

class BaseRepository<TEntity> : IRepository <TEntity> where TEntity : class
{
    internal ApplicationContext context;
    internal DbSet<TEntity> dbSet;

    public BaseRepository(ApplicationContext context)
    {
        this.context = context;
        this.dbSet = context.Set<TEntity>();
    }

    public virtual IEnumerable<TEntity> GetWithRawSql(string query, 
        params object[] parameters)
    {
        return dbSet.SqlQuery(query, parameters).ToList();
    }

    public virtual IEnumerable<TEntity> Get(
        Expression<Func<TEntity, bool>> filter = null,
        Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
        string includeProperties = "")
    {
        IQueryable<TEntity> query = dbSet;

        if (filter != null)
        {
            query = query.Where(filter);
        }

        if (includeProperties != null)
        {
            foreach (var includeProperty in includeProperties.Split
            (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
            {
                query = query.Include(includeProperty);
            }
        }
            

        if (orderBy != null)
        {
            return orderBy(query).ToList();
        }
        else
        {
            return query.ToList();
        }
    }

    public virtual TEntity GetByID(object id)
    {
        return dbSet.Find(id);
    }

    public virtual void Insert(TEntity entity)
    {
        dbSet.Add(entity);
    }

    public virtual void Delete(object id)
    {
        TEntity entityToDelete = dbSet.Find(id);
        Delete(entityToDelete);
    }

    public virtual void Delete(TEntity entityToDelete)
    {
        if (context.Entry(entityToDelete).State == EntityState.Detached)
        {
            dbSet.Attach(entityToDelete);
        }
        dbSet.Remove(entityToDelete);
    }

    public virtual void Update(TEntity entityToUpdate)
    {
        dbSet.Attach(entityToUpdate);
        context.Entry(entityToUpdate).State = EntityState.Modified;
    }
}

关于存储库的更多信息(工作单元模式 C#):

工作单元模式 C#

为单个事务使用单独的存储库可能会导致部分更新。 例如,假设您必须更新两个不同的实体类型作为同一事务的一部分。 如果每个都使用单独的数据库上下文实例,一个可能成功,另一个可能失败,确保所有存储库使用相同数据库上下文(从而协调所有更新)的一种方法是使用工作单元类。

public interface IUnitOfWork
{
    IRepository<Customer> Customers { get; }
    IRepository<Order> Orders { get; }
    void Commit();
}

下面是上面 IUnitOfWork 的实现方式的代码,

public class UnitOfWork : IUnitOfWork
{

    private ApplicationContext _dbContext;
    private BaseRepository<Customer> _customers;
    private BaseRepository<Order> _orders;

    public UnitOfWork(ApplicationContext dbContext)
    {
        _dbContext = dbContext;
    }

    public IRepository<Customer> Customers
    {
        get
        {
            return _customers ?? 
                (_customers=new BaseRepository<Customer>(_dbContext));
        }
    }

    public IRepository<Order> Orders
    {
        get
        {
            return _orders ?? 
                (_orders=new BaseRepository<Order>(_dbContext));
        }
    }

    public void Commit()
    {
        _dbContext.SaveChanges();
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM