Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implement a generic repository pattern using old ado.net

I am trying to implement the repository pattern using ado.net because of platform limitation.

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

How to complete the following abstract class...?

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

Update:
I will implement the domain specified repository later by inherent these two interface/class.

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

    public Foo GetSingle(int fooId) {

        var query = GetAll().FirstOrDefault(x => x.FooId == fooId);
        return query;
    }
}
like image 704
ca9163d9 Avatar asked May 23 '12 21:05

ca9163d9


2 Answers

If you're going from a legacy database that's filled with inconsistencies, and a ton of stored procedures and you are trying to hook it up to an ORM/Repository pattern, then you might find yourself getting really frustrated with implementing a Generic Repository pattern.

I know Generic Repository patterns are a huge hit in the tutorial sections these days when a lot of newer apps let things like Entity Framework and Active Record make the databases (remember this style implies no stored procedures or minimal uses of them). In these newer scenarios, the data tends to be a bit cleaner and makes it really easy to hook it up to some generic repository pattern as every entity pretty much has an ID.

like image 95
Max Alexander Avatar answered Oct 12 '22 13:10

Max Alexander


Not quite on topic, but I had similar problem, and here is my solution (can anyone help)

Create Identity class:

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

Create entyty class:

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

Repository interface(also you can only use an abstract class):

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

Create Generic abstract class:

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

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

that's all. Use in code:

    public class SomeService
{
    public void SomeeMethod()
    {
     int employeeId = 10; // for example
     EmployeeRepository repository = new EmployeeRepository();
     Employee employee = repository.GetById(employeeId);
     repository.Delete(employee);
     //...
    }
    }
like image 41
Alexander Brattsev Avatar answered Oct 12 '22 13:10

Alexander Brattsev