Search code examples
c#entity-frameworkgenericsdb-first

DB First with Base Entity Interface


Environment:

I am working in DB First Approach. I am having 3 tables in my database. All these tables have status field to indicate the record status. This is an integer field.

Scenario:

I created model diagram from this table using db first approach. Then i created a generic repository Interface and class for CRUD operations.

The following is interface;

public interface IGenericRepository<T> where T : class
{

    IQueryable<T> GetAll();
    Task<T> GetAsync(int id);
    void Add(T entity);
    void Delete(T entity);
    void Edit(T entity);
    Task<bool> SaveAsync();
}

The following is the generic Repository class

    public abstract class GenericRepository<C, T> :
        IGenericRepository<T> where T : class
                              where C : MyDBContext, new()
    {
    public virtual IQueryable<T> GetAll()
    {
        IQueryable<T> query = _entities.Set<T>();
        return query;
    }
//Removed other methods for clarity
}

Requirement:

In GetAll method, I need to check the status field and return only value = 1

Current Solution I have:

As this is generic repository, I can't access field in the methods. We can create a base Interface with Status field, then inherit it in generic repository and can use this field in the method.

Changes like below;

    public interface IGenericRepository<T> where T : class, IBaseEntity
    {
   //Methods removed for clarity
    }

    public abstract class GenericRepository<C, T> :
        IGenericRepository<T> where T : class, IBaseEntity
                              where C : MyDBContext, new()
    {
        public virtual IQueryable<T> GetAll()
        {
            IQueryable<T> query = _entities.Set<T>().Where(x => x.Status== 1);
            return query;
        }
}

Problems:

To work this, we need to inherit base interface to all my models. As the model is generated from Database, I manually added IBaseEntity into each model in the edmx tt file.

If my databse have any changes and i updated the diagram again, the manaully added interface is removed.

So any other alternative methods in DBFirst or my solution is wrong in DB First?


Solution

  • The classes that are generated by db-first tools usually have the partial specifier. This means that you can "extend" the definition by adding another partial class definition for the same class in a different file (that you control and won't be overwritten). Interfaces can be implemented on separate parts of the partial class.

    The generated file:

    public partial class MyEntity {} 
    

    Your separate file:

    public partial class MyEntity : IMyInterface {} 
    

    For more information you can see this question or the MSDN article on partial classes and methods.