8

Estoy tratando de implementar el patrón de repositorio usando ado.net debido a la limitación de la plataforma.Implementar un patrón de repositorio genérico usando ado.net antiguo

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(); 
} 

cómo llevar a cabo la siguiente clase abstracta ...?

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; 
    } 

Actualización:
voy a poner en práctica el repositorio de dominio especificado más adelante por estos dos inherente interfaz/clase.

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

    public Foo GetSingle(int fooId) { 

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

Respuesta

0

Está intentando construir una parte de lo que hace un asignador O tradicional. Este es un lote de trabajo. ¿Por qué no simplemente usar un ORM?

+1

agreed. Hay muchos ORM disponibles. –

+1

Agrego funciones a una aplicación heredada y no quiero traer ninguna DLL nueva. – ca9163d9

+1

Ok, entonces tienes un hombre mes de trabajo por hacer para implementar el método FindBy. Necesita crear cadenas de SQL a partir de expresiones. Esto no es trivial * en absoluto *. Te sugiero que cambies el diseño de tu interfaz para que no admita expresiones arbitrarias. Tal vez puedas admitir una secuencia where-select-orderby-top. Quizás eso es suficiente. – usr

6

En general, no es una buena idea tener un repositorio genérico. El repositorio es un concepto de dominio importante y no desea sobregeneralizarlo al igual que no quisiera generalizar sus entidades. El repositorio genérico es CRUDy y desvía el foco de su dominio. Por favor, considere this article by Greg Young.

En una nota relacionada, exponiendo IQueryable introducirá tight coupling además de hacer que su código sea menos dominio y más datos impulsada.

+0

He actualizado la pregunta para explicar el problema de dominio/datos. – ca9163d9

0

Si va desde una base de datos heredada que está llena de inconsistencias, y un montón de procedimientos almacenados y está tratando de conectarla a un patrón ORM/Repositorio, entonces puede encontrarse realmente frustrado con la implementación de un Patrón de repositorio genérico.

Sé que los patrones de repositorio genéricos son un gran éxito en las secciones de tutoriales en estos días cuando muchas aplicaciones más nuevas permiten que entidades como Entity Framework y Active Record hagan las bases de datos (recuerde que este estilo no implica procedimientos almacenados ni usos mínimos). . En estos escenarios más nuevos, los datos tienden a ser un poco más limpios y hacen que sea realmente fácil conectarlo a un patrón de repositorio genérico ya que cada entidad tiene una ID.

0

No del todo en el tema, pero no tenía problema similar, y aquí está mi solución (puede ayudar a nadie)

Crear clase de Identidad:

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

Crear clase entyty:

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

Interfaz de repositorio (también se puede usar una clase abstracta):

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); 
    } 

Crear Genérico clase abstracta:

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); 
    } 

e implementar 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 = [email protected]"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(); 
     } 
    } 

eso es todo.Usar en el código:

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