Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to cast DbSet<T> to List<T>

Given the following simplified Entity Framework 6 context, I am trying to populate a List with the entities but having problems with how to cast (I believe) via reflection.

public class FooContext : DbContext
{
   public virtual IDbSet<FooClass> Foo { get; set; }    
   //...
}

public class FooClass
{
    public int Id{ get; set; }
    public string Name {get; set; }
    //...    
}

public main()
{
     using (var context = new FooContext())
     {
         var sets = typeof(FooContext).GetProperties().Where(pi => pi.PropertyType.IsInterface && pi.PropertyType.GetGenericTypeDefinition().ToString().ToLower().Contains("idbset"));

         foreach (var set in sets)
         {
             //When I debug and enumerate over 'value' the entire results are shown so I believe the reflection part is OK.
             var value = set.GetValue(context, null);

             //Always returns null. How can I cast DbSet<T> to List<object> or List<T>? 
             var list = value as List<object>();

             //...
         }
     }
}

I'm doing this for utility method for some integration testing I am doing. I am trying to do this without using direct inline SQL calls (using SqlConnection and SqlCommand etc) to access the database (as the datastore may change to Oracle etc).

like image 458
Kyle Avatar asked Jun 15 '15 12:06

Kyle


People also ask

What is the difference between DbSet and DbContext?

Intuitively, a DbContext corresponds to your database (or a collection of tables and views in your database) whereas a DbSet corresponds to a table or view in your database.

What does DbSet attach do?

Attach is used to repopulate a context with an entity that is known to already exist in the database. SaveChanges will therefore not attempt to insert an attached entity into the database because it is assumed to already be there.

What is DbSet in .NET core?

The DbSet class represents an entity set that can be used for create, read, update, and delete operations. The context class (derived from DbContext ) must include the DbSet type properties for the entities which map to database tables and views.

What is DbSet and entity set?

In Entity Framework Core, the DbSet represents the set of entities. In a database, a group of similar entities is called an Entity Set. The DbSet enables the user to perform various operations like add, remove, update, etc. on the entity set.


2 Answers

IDBSet inherits from IQueryable<TEntity>, IEnumerable<TEntity>, IQueryable, and IEnumerable, so you can't directly cast it to a list that way. You could get a List<TEntity> of all entities in the DBSet though by using .ToList() or .ToListAsync()

THis creates a copy of all entities in memory though, so you should consider operating with LINQ directly on the DBSet

like image 137
LInsoDeTeh Avatar answered Sep 20 '22 09:09

LInsoDeTeh


Alongside VicYam's answer, here is an easier way with a detailed explanation.

Once you add the System.Linq namespace, you no longer need to get IQueryable and then convert to a List. Instead, you will get the extension methods on the DbSet object.

What does this mean? You can simply return the DbSet by itself as it inherits from IEnumerable. The consumer, possibly a dev, can then do a .ToList or any other list type they may need.

Easiest

This will return the DbSet as is, which already inherits from IEnumerable which is a list type that can be then converted to a List.

List<ObjectType> list = new List<ObjectType>();
using (var context = new FooContext())
{
    list = context.Foo;
}

Alternative

You can immediately convert from IEnumerable to a List.

using (var context = new FooContext())
{
    var list = context.Foo.ToList();
}

Still want VicYam's answer but as a one line?

using (var context = new FooContext())
{
    var list = context.Foo.AsQueryable().ToList();
}
like image 31
AzzamAziz Avatar answered Sep 18 '22 09:09

AzzamAziz