views:

38

answers:

2

I'm working a simple EF/MVC app and I'm trying to implement some Repositories to handle my entities. I've set up a BaseObject Class and a IBaseRepository Interface to handle the most basic operations so I don't have to repeat myself each time:

public abstract class BaseObject<T>
    {
        public XA.Model.Entities.XAEntities db;
        public BaseObject()
        {
            db = new Entities.XAEntities();
        }

        public BaseObject(Entities.XAEntities cont)
        {
            db = cont;
        }

        public void Delete(T entity)
        {
            db.DeleteObject(entity);
            db.SaveChanges();
        }

        public void Update(T entity)
        {
            db.AcceptAllChanges();
            db.SaveChanges();
        }
   }

    public interface IBaseRepository<T>
    {
        void Add(T entity);

        T GetById(int id);
        IQueryable<T> GetAll();
    }

But then I find myself having to implement 3 basic methods in every Repository ( Add, GetById & GetAll):

public class AgencyRepository : Framework.BaseObject<Agency>, Framework.IBaseRepository<Agency>
    {
        public void Add(Agency entity)
        {
            db.Companies.AddObject(entity);
            db.SaveChanges();
        }
        public Agency GetById(int id)
        {
            return db.Companies.OfType<Agency>().FirstOrDefault(x => x.Id == id);
        }
        public IQueryable<Agency> GetAll()
        {
            var agn = from a in db.Companies.OfType<Agency>()
                      select a;
            return agn;
        }
    }

How can I get these into my BaseObject Class so I won't run in conflict with DRY.

A: 

Unless your base class is able to implement the interface (and then you can inherit it's implementation) you're prety much stuck writing them each time. If the steps are different for each child, then your not repeating yourself, even though it kinda feels like it.

As an off topic remark, rather than creating the db object in your base constructor, you may be able to save your self some pain down the road and dependency inject it instead. It will make your repository easier to unit test if your putting any code in there that's worthy of testing.

Josh Sterling
How do I get rid of the interface and implement those 3 methods on the abstract base class?
hminaya
Rather than having your repository implement the interface directly, make your base class implement the interface `public abstract class BaseObject<T> : IBaseRepository<T>`Or if you dont need the interface, get rid of the interface and just have the base class contain those functions
Josh Sterling
I tried it but wasn't able to add the methods to the base class...
hminaya
Looking at your add method, if `db.Companies.AddObject(entity)` is done for all your repositories, why cant it go in the base class? If however a `ClientRepository` needs to do `db.Clients.AddObject(entity)` instead, then DRY isn't in play because each repository is doing something slightly different.
Josh Sterling
A: 

You can easily do this with T4 in EF 4. With more work, you can do it with T4 in EF 1.

But I recommend that you don't. MyEntity.Update() will be a fiction. The EF doesn't allow you to save part of the changes to a context (like one specific object). So your method will do something very different than it appears to do. IMHO this design is working against the EF. It also makes your entities persistence-aware by design.

Craig Stuntz