3

我有一个数据库映射实体框架的所有实体,实体框架动态DbSet为

我需要实现获得基于一个参数,我通过项目的AA名单的一般方法:

getGenericList("product"); // returns the list of products 
getGenericList("customer"); // returns the list of customers 

我需要动态获取dbSet。我的方法是实施这样的:

public static List<object> getGenericList(string entityType) 
    { 
     List<object> myDynamicList = new List<object>(); 
     using (cduContext db = new cduContext()) 
     { 
      DbSet dbSet = db.getDBSet(entityType); 
      var myDynamicList = dbSet.Select(p => p).ToList(); 
     } 
     return new List<object>(); 
    } 

dbSets通过EF代码首先是自动生成的:

public DbSet<Product> Products { get; set; } 
public DbSet<Custommer> Custommers { get; set; } 

getDBSet(entityType)方法的背景下实现的,就像这样:

public DbSet<T> getDBSet<T>(string entityName) where T : class 
    { 
     switch (entityName) 
     { 

      case "product": 
       return Products; 

      case "custommer": 
       return Custommers; 

然后我得到这个错误:

Cannot implicitly convert type 'System.Data.Entity.DbSet' to 'System.Data.Entity.DbSet'

任何想法请!?

N.B. ,dbContext的方法Set()不正确;该类型应该明确给出...

+0

您可能想要在实际代码中更正“custommer” - >“customer”的拼写。 – MEMark

回答

2

这是更好地从字符串作为类型望而却步,并将它们映射到真正的类型;这是一种代码味道。相反,使用它们自己的类型。无论哪种方式,让我们重构使用getGenericList()方法的代码来使用泛型。如果不能从字符串脱身,做一个调用getGenericList(),而不是映射这个方法里面,因为我们下面你所阐述的模式代码的映射。

还要注意,在原始getGenericList()你总是返回一个空列表,而不是您通过EF获得的名单。您还使用了2个不同的myDynamicList变量;外部的一个被using语句范围中的掩码所掩盖,这就是为什么您不会收到编译器错误。一旦using超出范围,内部myDynamicList也超出范围。我在这里解决了这个问题。

public static List<T> getGenericList<T>() 
{ 
    List<T> myDynamicList; 

    using (cduContext db = new cduContext()) 
    { 
     // consider using exception handling here as GetDbSet might get an invalid type 
     DbSet dbSet = db.GetDbSet<T>(); 
     myDynamicList = dbSet.Select(p => p).ToList(); 
    } 

    if (myDynamicList != null && myDynamicList.Count() > 0) 
    { 
     return myDynamicList; 
    } 
    return new List<T>(); 
} 

// in your context class 
public DbSet<T> GetDbSet<T>() where T : class 
{ 
    return this.Set<T>(); 
} 

// this is the code that calls getGenericList(); put this inside a function somewhere. 
// entityName holds a string value, set previously 
switch(entityName.ToLower()) // making entityName case insensitive 
{ 
    case "product": 
     return getGenericList<Product>(); 

    case "customer": 
     return getGenericList<Customer>(); 
} 

希望你不会有要映射过多实体类型,否则你会用一个巨大的switch声明结束了。同样,如果您使用的是switch声明,通常可能表示您需要重新考虑您的方法。

0

要避免switch,您可以通过组件限定名称查找类型,然后从中获取DbSet。以这种方式检索的DbSet不是通用的<>,因此您可以执行的操作更受限制。

您可以通过使用已知实体类型(例如Product)获取程序集限定名称,获取程序集限定名称,然后用所需名称替换“Product”以获取类型。

这个例子是从Breeze应用,其中某些查找实体可以通过名称从客户端请求简化。

public async Task<List<object>> GetGenericList(string entityType) 
{ 
    using (var context = new MyContext()) 
    { 
    var aqtemp = typeof(Product).AssemblyQualifiedName; // template for qualified name 

    var aqname = aqtemp.Replace("Product", entityType); // qualified name for entityType 

    var type = Type.GetType(aqname, true, true);  // Type for entityType 

    var list = await context.Set(type).ToListAsync(); // query the entities 
    return list; 
    } 
}