6

Back in EF 4 it was not possible. Is it possible to use interfaces with a DbSet in EF6 or EF Core?

public class LfSp3Ctx : DbContext, ILfSp3Ctx
{
    public DbSet<ILfSp3Project> ProjectSE { get; set; }
}
Amal K
  • 4,359
  • 2
  • 22
  • 44
Abhijeet
  • 13,562
  • 26
  • 94
  • 175

1 Answers1

6

It is possible, but it requires some trickery. EF will only instantiate DbSet types directly. Thus, you'd have to create your own interface that wraps/exposes all the DbSet methods you want and the actual implementation takes the DbSet instance in its constructor. Then on the DbContext class, you have to do something like this:

IDbSet<DigimonEntity> DigimonRepository => new DbSetRepository<DigimonEntity>(this.Digimons);

DbSet<DigimonEntity> Digimons { get; set; }

public class DbSetRepository<T> : IDbSet<T> where T : class
{
    private readonly DbSet<T> _set;
    public DbSetRepository(DbSet<T> set) => _set = set;

    public Type ElementType => ((IQueryable<T>)_set).ElementType;
    public Expression Expression => ((IQueryable<T>)_set).Expression;
    public IQueryProvider Provider => ((IQueryable<T>)_set).Provider;
    public IEnumerator<T> GetEnumerator() => ((IEnumerable<T>)_set).GetEnumerator();
    IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable<T>)_set).GetEnumerator();

    void IDataStoreRepositoryWrite<T>.Add(T entity) => _set.Add(entity);
    void IDataStoreRepositoryWrite<T>.Update(T entity) => _set.Update(entity);
    void IDataStoreRepositoryWrite<T>.Delete(T entity) => _set.Remove(entity);

    Task IDataStoreRepositoryWrite<T>.AddAsync(T entity, CancellationToken token) => _set.AddAsync(entity, token);
}

Something like this. Mine is kind of specific to the implementation I was trying to pull off at the time. :)

Daniel Lorenz
  • 4,178
  • 1
  • 32
  • 39
  • 2
    In your example you're not using the interface with the dbset as asked in the question, am I wrong? You're using the interface IDbSet but the question was if one can use an interface as type of the DbSet – Michele mpp Marostica Jul 03 '19 at 21:39
  • Ah, you are right. Though, technically you could by wrapping it like I show here. You would need a real DbSet that implements the type that would be passed into a wrapper that would expose the interface. It would then use that DbSet implementation indirectly... But not sure it would really gain you that much. – Daniel Lorenz Jul 04 '19 at 03:04