5

我有一个用实体框架映射的数据库,

我需要实现一个通用方法来获取基于我传递的参数的项目列表:

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

mydbSets首先由 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;

然后我得到了这个错误:

无法将类型“System.Data.Entity.DbSet”隐式转换为“System.Data.Entity.DbSet”

请有任何想法!?

NB , 的方法Set()不行dbContext;类型应该明确给出......

4

2 回答 2

4

最好远离字符串作为类型并将它们映射到真实类型;那是代码的味道。相反,请使用类型本身。无论哪种方式,让我们重构使用该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声明,通常这可能表明您需要重新考虑您的方法。

于 2013-06-04T03:05:42.553 回答
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;
  }
}
于 2017-11-06T08:10:02.487 回答