it-swarm.com.de

Finden Sie ein angegebenes generisches DbSet dynamisch in einem DbContext, wenn ich eine Entität habe

Ich habe folgende Klassen und DbContext:

public class Order:BaseEntity
{
   public Number {get; set;}
}
Product:BaseEntity;
{
  public Name {get; set;} 
}

public class Context : DbContext
{
    ....
    public DbSet<Order> Orders { set; get; }
    public DbSet<Product> Products { set; get; }
    ....
}   

Ich habe eine Liste von Objekten, die auch meinem Kontext hinzugefügt werden sollen, aber ich weiß nicht, wie ich entsprechend dem jeweiligen Entitätstyp passende generische DbSet dynamisch finden kann. 

IList<BaseEntity> list = new List<BaseEntity>();
Order o1 = new Order();
o1.Numner = "Ord1";
list.Add(o1);

Product p1 = new Product();
p1.Name = "Pencil";
list.Add(p1);

Context cntx = new Context();  
foreach (BaseEntity entity in list)
{
      cntx.Set<?>().Add(entity);         
}

Wie kann ich das machen?

23
Masoud

DbContext hat eine Methode namens Set, die Sie verwenden können, um eine nicht generische DbSet zu erhalten, z.

var someDbSet = this.Set(typeof(SomeEntity));

Also in deinem Fall:

foreach (BaseEntity entity in list)
{
      cntx.Set(entity.GetType()).Add(entity);         
}
34
Pablo Romeo

In der Frage wird keine EF-Version angegeben, und die vorgeschlagene Antwort funktioniert für Entity Framework Core nicht mehr (DbContext hat im EF-Core mindestens zum Zeitpunkt dieser Antwort keine generische set-Methode). 

Sie können jedoch immer noch eine funktionierende Erweiterungsmethode verwenden, die die Antwort von Jon Skeet auf diese Frage verwendet. Mein Code wird der Einfachheit halber unten hinzugefügt.

** Update: Der generische Funktionsaufruf wurde hinzugefügt und dank des Kommentars von Shaddix IQueryable <T> zurückgegeben. 

    public static IQueryable Set(this DbContext context, Type T)
    {

        // Get the generic type definition
        MethodInfo method = typeof(DbContext).GetMethod(nameof(DbContext.Set), BindingFlags.Public | BindingFlags.Instance);

        // Build a method with the specific type argument you're interested in
        method = method.MakeGenericMethod(T);

        return method.Invoke(context, null) as IQueryable;
    }

    public static IQueryable<T> Set<T>(this DbContext context)
    {
        // Get the generic type definition 
        MethodInfo method = typeof(DbContext).GetMethod(nameof(DbContext.Set), BindingFlags.Public | BindingFlags.Instance);

        // Build a method with the specific type argument you're interested in 
        method = method.MakeGenericMethod(typeof(T)); 

        return method.Invoke(context, null) as IQueryable<T>;
    } 
13
user3141326

Zusätzlich zur Antwort von Pablo:

Sie können Ihrem Projekt eine Klasse hinzufügen:

namespace System.Data.Entity
{
  public static class EntityFrameworkExtensions
  {
    public static IEnumerable<object> AsEnumerable(this DbSet set)
    {
      foreach (var entity in set)
        yield return entity;
    }
  }
}

Diese Klasse fügt eine Extention-Methode AsEnumerable zur DbSet-Instanz hinzu und wenn Sie sie beispielsweise für Count oder filter einige Zeile verwenden möchten:

var someDbSet = this.Set(typeof(SomeEntity));
var count = (from a in someDbSet.AsEnumerable() select a).Count();
0
combo_ci