动态查找CRUD操作的实际DbSet

时间:2018-12-12 16:19:41

标签: c# entity-framework

我已经在该站点上搜索,无法从上下文中获取实际的DbSet。我正在尝试根据表名动态检索每个dbset。

 var dynamicdbset = GetDbSetByTableName(uploadTableName); //Dbset name is Mytables


  private dynamic GetDbSetByTableName(string tableName)
        {
            MyEntities context = new MyEntities();
            System.Reflection.PropertyInfo[] properties = typeof(ClearGUIEntities).GetProperties();
            var prop = properties.FirstOrDefault(p => p.Name == tableName + "s");

            using (var db = new MyEntities())
            {
                var dbset = prop?.GetValue(db);
                return dbset;
            }

        }

这里的问题是它正在返回一些通用的dbset,但是我不能使用linq,也不能做像这样的简单操作

dynamicdbset.Where(t = > t.Id == 123).Single();

我需要能够通过表名动态获取dbset,并以与我专门创建它的方式相同的方式查询数据

var value = context.MyTables.FirstorDefault()

1 个答案:

答案 0 :(得分:1)

返回的动态DbSet实际上只是实际DbSet对象的包装,您可以将其简单地转换为对象。但是问题是,如果不使用generic method,就无法推断出DbSet的类型。

以下方法会起作用,但可能最不推荐:

private IEnumerable<T> GetDbSetByTableName<T>(string tableName)
{
    System.Reflection.PropertyInfo[] properties = typeof(ClearGUIEntities).GetProperties();
    var prop = properties.FirstOrDefault(p => p.Name == tableName + "s");

    using (var db = new ClearGUIEntities())
    {
        var dbset = prop?.GetValue(db);

        return new List<T>(dbset as IEnumerable<T>);
    }
}

现在,要解决此问题,我们至少有两个选择:

  1. 创建一个由所有DbSet实现的接口(具有所需的所有基本属性)。这样,我们可以在转换时无需指定类型就可以投射动态对象。
  2. 退回IEnumerable<dynamic>,可以即时投放。

选项1

public interface IBaseProperties
{
    int Id { get; set; }
    string Name { get; set; }
}

public class MyTable : IBaseProperties
{
    // Add these with either T4 templates or create partial class for each of these entities
    public int Id { get; set; }
    public string Name { get; set; }
}

private IEnumerable<IBaseProperties> GetDbSetByTableName(string tableName)
{
    System.Reflection.PropertyInfo[] properties = typeof(ClearGUIEntities).GetProperties();
    var prop = properties.FirstOrDefault(p => p.Name == tableName + "s");

    using (var db = new ClearGUIEntities())
    {
        var dbset = prop?.GetValue(db);

        return new List<IBaseProperties>(dbset as IEnumerable<IBaseProperties>);
    }
}

// ...
// Using it
// ...

var dynamicdbset = GetDbSetByTableName("MyTable");

int id = dynamicdbset.FirstOrDefault().Id;

选项2

private IEnumerable<dynamic> GetDbSetByTableName(string tableName)
{
    System.Reflection.PropertyInfo[] properties = typeof(ClearGUIEntities).GetProperties();
    var prop = properties.FirstOrDefault(p => p.Name == tableName + "s");

    using (var db = new ClearGUIEntities())
    {
        var dbset = prop?.GetValue(db);

        return new List<dynamic>(dbset as IEnumerable<dynamic>);
    }
}

// ...

// At this point, you can basically access any property of this entity
// at the cost of type-safety
string id = dynamicdbset.FirstOrDefault().Id;
string name = dynamicdbset.FirstOrDefault().Name;

顺便说一句,强制转换为List<T>是因为您正在使用using块之外的对象,此时该对象将被处置。

new List<IBaseProperties>(dbset as IEnumerable<IBaseProperties>);