web-dev-qa-db-fra.com

Comment convertir DbSet <T> en Liste <T>

Compte tenu du contexte simplifié Entity Framework 6 suivant, j'essaie de renseigner une liste avec les entités, mais je ne parviens pas à trouver comment (j’estime) le transtypage (je crois) via la réflexion.

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>();

             //...
         }
     }
}

Je fais cela pour la méthode utilitaire pour certains tests d'intégration que je fais. J'essaie de le faire sans utiliser d'appels SQL directs en ligne (à l'aide de SqlConnection et SqlCommand, etc.) pour accéder à la base de données (car le magasin de données peut passer à Oracle, etc.).

8
Kyle

IDBSet hérite de IQueryable<TEntity>, IEnumerable<TEntity>, IQueryable et IEnumerable, de sorte que vous ne pouvez pas le convertir directement dans une liste de cette façon. Vous pourriez obtenir un List<TEntity> de toutes les entités de la DBSet bien que vous utilisiez .ToList() ou .ToListAsync()

Cela crée cependant une copie de toutes les entités en mémoire, vous devriez donc envisager d’utiliser LINQ directement sur le DBSet.

9
LInsoDeTeh
//dont forget using System.Linq;
using (var context = new FooContext())
{
   IQueryable<FooClass> rtn = from temp  in context.Foo select temp;
   var list = rtn.ToList();
}
8
VicYam

En plus de la réponse de VicYam, voici une méthode plus simple avec une explication détaillée.

Une fois que vous avez ajouté l'espace de noms System.Linq, vous n'avez plus besoin d'obtenir IQueryable, puis de le convertir en List. Au lieu de cela, vous obtiendrez les méthodes d'extension sur l'objet DbSet.

Qu'est-ce que ça veut dire? Vous pouvez simplement renvoyer la DbSet par elle-même, car elle hérite de IEnumerable. Le consommateur, éventuellement un développeur, peut alors créer un .ToList ou tout autre type de liste dont il pourrait avoir besoin.

Le plus facile

Ceci retournera la DbSet telle quelle, qui hérite déjà de IEnumerable, qui est un type de liste pouvant être ensuite converti en une List.

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

Alternative

Vous pouvez immédiatement convertir de IEnumerable en List.

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

Je veux toujours la réponse de VicYam mais en une seule ligne?

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

Vous ne pouvez pas le lancer. Créez simplement un nouveau List<T> à partir de vous DbSet via ToListAsync<T>() À partir de IQueryable en le énumérant de manière asynchrone ou simplement via synchrone ToList()

Aussi, je pense qu'il vaut mieux créer une réalisation concrète pour vos scénarios. Maintenant, créez pour EF. Lorsque vous commencerez à utiliser NHibernate, par exemple, créez un test, etc. Ce sera plus simple pour le support futur, puis d'essayer de créer quelque chose de générique, ce qui sera plus compliqué pour le correctif et le débogage.

Pour votre information, êtes-vous sûr que vous aurez besoin de ces tests d’intégration? Peut-être mieux de vérifier que vos mappages/implémentations fonctionnent avec votre base de données. Je pense que ce sera la partie la plus importante. Bien sûr si vous ne l'aviez pas fait avant.

1
ivamax9
private StudentDatabaseEntities db = new StudentDatabaseEntities();

public List<StudentDatabaseDbTableModel> AllProducts()
{
    return db.StudentDatabaseDbTableModel.ToList();
}   

db.StudentDatabaseDbTableModel est de type DbSet. ToList est une méthode dans la classe DbSet. La méthode ToList convertit un objet de type DbSet en type de liste.

0
Siddarth Kanted