【问题标题】:Implement a generic repository pattern using old ado.net使用旧的 ado.net 实现通用存储库模式
【发布时间】:2012-05-23 21:12:08
【问题描述】:

由于平台限制,我正在尝试使用 ado.net 实现存储库模式。

public interface IGenericRepository<T> : IDisposable where T : class
{
    IQueryable<T> GetAll();
    IQueryable<T> FindBy(Expression<Func<T, bool>> predicate);
    void Add(T entity);
    void Delete(T entity);
    void Edit(T entity);
    void Save();
}

如何完成下面的抽象类...?

public abstract class GenericRepository<C, T> :
    IGenericRepository<T>
    where T : class
    where C : IDbDataAdapter, new()
{

    private C dbDataAdapter = new C();
    protected C DB
    {
        get { return dbDataAdapter; }
        set { dbDataAdapter = value; }
    }

    public virtual IQueryable<T> GetAll()
    {
        DataTable dt;
        dbDataAdapter.fill(dt);
        IQueryable<T> query = dt....?;
        return query;
    }

    public IQueryable<T> FindBy(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
    {

        IQueryable<T> query = dbDataAdapter.???Set<T>???().Where(predicate);
        return query;
    }

更新:
稍后我将通过固有的这两个接口/类来实现域指定的存储库。

public class FooRepository :
    GenericRepository<FooBarEntities, Foo>, IFooRepository {

    public Foo GetSingle(int fooId) {

        var query = GetAll().FirstOrDefault(x => x.FooId == fooId);
        return query;
    }
}

【问题讨论】:

    标签: c# design-patterns orm domain-driven-design repository-pattern


    【解决方案1】:

    拥有通用存储库通常不是一个好主意。存储库是一个重要的领域概念,您不想过度概括它,就像您不想概括您的实体一样。通用存储库是 CRUDy 并将焦点从您的域转移。请考虑this article by Greg Young

    在相关说明中,公开 IQueryable 将引入 tight coupling,此外还会使您的代码更少和更多数据驱动。

    【讨论】:

    • 我已更新问题以解释域/数据驱动的问题。
    【解决方案2】:

    主题不完全,但我有类似的问题,这是我的解决方案(任何人都可以帮忙)

    创建身份类:

    public class Identity
        {
            public int Id { get; set; }
        }
    

    创建实体类:

    public class Employee: Identity
        {
            public string Name { get; set; }
            public string Surname { get; set; }
            public int Age { get; set; }
        }
    

    Repository 接口(也只能使用抽象类):

    interface IRepository<T> where T: Identity
        {
            T GetById(int id);
            ICollection<T> GetAll();
            ICollection<T> GetAll(string where);
            void Update(T entity);
            void Insert(T entity);
            bool Delete(T entity);
            bool Delete(ICollection<T> entityes);
        }
    

    创建通用抽象类:

    public abstract class AbstractRepository<T>: IRepository<T> where T : Identity
        {
            protected abstract string TableName { get; }
    
            protected abstract T DataRowToModel(DataRow dr);
    
            protected virtual ICollection<T> DataTableToCollection(DataTable dt)
            {
                if (dt == null)
                {
                    return null;
                }
                return dt.AsEnumerable().Select(x => DataRowToModel(x)).ToList();
            }
    
            public virtual T GetById(int id)
            {
                var query = $"select * from {TableName} where id = {id}";
                //the data access layer is implemented elsewhere
                DataRow dr = DAL.SelectDataRow(query); 
                return DataRowToModel(dr);
            }
    
            public virtual void Delete(T entity)
            {
                if (entity.Id == 0 )
                {
                    return;
                }
                var query = $"delete from {TableName} where id = {entity.Id}";
                DAL.Query(query);
            }
    
            public virtual void Delete(ICollection<T> entityes)
            {
                var collectionId = IdentityCollectionToSqlIdFormat(entityes);
                if (string.IsNullOrEmpty(collectionId))
                {
                    return;
                }
                var query = $"delete from {TableName} where id in ({collectionId})";
                DAL.Query(query);
            }
    
            public virtual ICollection<T> GetAll()
            {
                var query = $"select * from {TableName}";
                DataTable dt = DAL.SelectDataTable(query);
                return DataTableToCollection(dt);
            }
    
            public virtual ICollection<T> GetAll(string where)
            {
                var query = $"select * from {TableName} where {where}";
                DataTable dt = DAL.SelectDataTable(query);
                return DataTableToCollection(dt);
            }
    
            protected virtual string IdentityCollectionToSqlIdFormat(ICollection<T> collection)
            {
                var array = collection.Select(x => x.Id);
                return string.Join(",", array);
            }
    
            public abstract bool Update(T entity);
            public abstract bool Insert(T entity);
        }
    

    并实现EmployeeRepository:

    public class EmployeeRepository : AbstractRepository<Employe>
        {
            protected sealed override string TableName
            {
                get
                {
                    return "dbo.Employees";
                }
            }
    
            protected sealed override Employe DataRowToModel(DataRow dr)
            {
                if (dr == null)
                {
                    return null;
                }
                return new Employe
                {
                    Id = dr.Field<int>("id"),
                    Name = dr.Field<string>("name"),
                    Surname = dr.Field<string>("surname"),
                    Age = dr.Field<int>("age")
    
                };
            }
    
    
            public override void Insert(Employe entity)
            {
                var query = $@"insert into {TableName} (name, surname, age)
                                values({entity.Name},{entity.Surname},{entity.Age})";
                DAL.Query(query);
            }
    
            public override bool Update(Employe entity)
            {
                throw new NotImplementedException();
            }
        }
    

    就是这样。在代码中使用:

        public class SomeService
    {
        public void SomeeMethod()
        {
         int employeeId = 10; // for example
         EmployeeRepository repository = new EmployeeRepository();
         Employee employee = repository.GetById(employeeId);
         repository.Delete(employee);
         //...
        }
        }
    

    【讨论】:

    • 对不起,没有。很久以前了
    【解决方案3】:

    如果您从一个充满不一致和大量存储过程的遗留数据库出发,并试图将其与 ORM/Repository 模式挂钩,那么您可能会发现自己对实现 Generic 感到非常沮丧存储库模式。

    我知道现在通用存储库模式在教程部分很受欢迎,因为许多较新的应用程序让 Entity Framework 和 Active Record 之类的东西创建数据库(请记住,这种风格意味着没有存储过程或对它们的最小使用)。在这些较新的场景中,数据往往更干净一些,并且很容易将其连接到一些通用存储库模式,因为每个实体几乎都有一个 ID。

    【讨论】:

      【解决方案4】:

      您正在尝试构建典型 OR 映射器的一部分。这是很多的工作。为什么不直接使用 ORM?

      【讨论】:

      • 同意。有很多可用的 ORM。
      • 我正在为旧版应用程序添加功能,不想引入任何新的 DLL。
      • 好的,那么您有一个月的工作要做来实现 FindBy 方法。您需要从表达式创建 SQL 字符串。这不是微不足道的在所有。我建议您将界面设计更改为不支持任意表达式。也许您可以支持 where-select-orderby-top 序列。也许这就够了。
      猜你喜欢
      • 2017-07-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-26
      • 1970-01-01
      • 1970-01-01
      • 2011-07-20
      相关资源
      最近更新 更多