2

I currently have the following working code:

        private Converter RemoveAll<T>(List<T> databaseSet) {
             databaseSet
                .ForEach(item =>  this.myContext.Remove(item));
            return this;
        }

which I can invoke like:

this.RemoveAll(this.myContext.Widgets.ToList());
this.RemoveAll(this.myContext.WhositsWhatsits.ToList());
// etc.

Where this.myContext is an instance of MyContext which extends DbContext; and Widgets, WhositsWhatsits, etc. are all instances of DbSet.

Because I always need to change the DbSet to a List, I'd rather just pass the DbSet as a parameter, like:

this.RemoveAll(this.myContext.Widgets);
this.RemoveAll(this.myContext.WhositsWhatsits);
// etc.

But if I change the method to:

        private Converter RemoveAll<T>(DbSet<T> databaseSet) {
             databaseSet.ToList()
                .ForEach(item =>  this.myContext.Remove(item));
            return this;
        }

The compiler complains "The type 'T' must be a reference type in order to use it as a parameter 'TEntity' in the generic type or method 'DbSet'.

Is it possible to modify this method so I can remove the need to invoke ToList() before calling it?

Brian Kessler
  • 2,187
  • 6
  • 28
  • 58
  • 2
    You can add the constraint ```where T : class```. – devsmn May 11 '20 at 11:17
  • 1
    `where T : class`? However, you might look at repository pattern, pass `DbContext` to it and encapsulate all CRUD operations – Pavel Anikhouski May 11 '20 at 11:17
  • 1
    are you looking for the [Set](https://learn.microsoft.com/en-us/dotnet/api/system.data.entity.dbcontext.set?view=entity-framework-6.2.0) method which can access different tables and be specified by a generic parameter. This way you don't even need to pass the dbset as parameter. Only specify it in the generic section – Mong Zhu May 11 '20 at 11:34
  • 1
    @PavelAnikhouski except... Entity Framework DbContext is *already* an implementation of the repository pattern. Wrapping it again *can* be an antipattern – pinkfloydx33 May 11 '20 at 12:17

2 Answers2

3

The DbSet is restricted to have reference types as generic parameters. Therefore, you need to restrict your method to also work only for reference types. It can be acheved by using where clause as below.

private Converter RemoveAll<TEntity>(DbSet<TEntity> databaseSet) where TEntity : class
MistGun
  • 162
  • 8
1

Instead of using remove method, use removerange where you can avoid Call to ToList(). I have provided an extension method that will reduce code even more.

public static class DbContextExtension
{
    public static void RemoveAll<Tinput>(this DbSet<Tinput> dbset) where Tinput : class
    {
        dbset.RemoveRange(dbset);
    }
}

usage will be like.

 this.myContext.Widgets.RemoveAll();

if u dont need extension method, just use

dbset.RemoveRange(dbset);

neelesh bodgal
  • 632
  • 5
  • 14