在不知道对象类型(类/表)的情况下查询实体框架实体

时间:2017-09-18 17:59:02

标签: c# asp.net-mvc entity-framework

我想知道,如果它首先是可能的话,我将如何使用ID和表名来查询数据库(使用EF)。

例如,将函数编写为:

QueryDynamicData(string tableName, long entityID){return GetItem(tableName, entityID);}

可以这样称呼:

var entry = QueryDynamicData("Person", 143);

为了澄清,这是针对使用实体框架的MVC ASP.Net项目。

提前致谢!

修改

按照@JPVenson的例子,我想出了以下代码。请注意,它返回了一个字典列表,即使Id是唯一的,因为我正在考虑当我们想要获得动态表的所有结果而不仅仅是Id时。 (这只是概念水平的证明)

public List<Dictionary<string, object>> QueryDynamicData(string table, int entityID)
    {
        try
        {
            //Get the table desired based on the table name passed
            PropertyInfo dbSetInfo = DBContext.GetType().GetProperties().FirstOrDefault(p => p.Name.ToLower().Equals(table.ToLower()));

            //Return all results from the table into IQueryable set where Id = entityID passed
            IQueryable anyDbSet = ((IQueryable)dbSetInfo.GetValue(DBContext)).Where("Id=" + entityID);

            List<Dictionary<string,object>> listObjects = new List<Dictionary<String, Object>>();

            //Iterate through results
            foreach (Object entity in anyDbSet)
            {
                //Create dictionary of Field Name, Field Value from results
                Dictionary<string, object> listDBValues = entity.GetType().GetProperties().ToDictionary(propertyInfo => propertyInfo.Name, propertyInfo => propertyInfo.GetValue(entity));

                //Add dictionary to list of dictionaries - useful for returning list of found results instead of just one
                listObjects.Add(listDBValues);
            }

            //Return list of dictionaries
            return listObjects;
        }
        catch (Exception e) { }
        return null;
    }

2 个答案:

答案 0 :(得分:2)

是的,你可以。 ScottGu有一个博客

https://weblogs.asp.net/scottgu/dynamic-linq-part-1-using-the-linq-dynamic-query-library

(DynamicLinq https://github.com/kahanu/System.Linq.Dynamic/wiki的MS版本)

包含名为DynamicLinq的lib的wiki。我目前在项目中使用它,它将适合您的方法。

你仍然必须包装它并使用一些反射来构建一个合适的IQueryable但它为你做了很多工作

编辑代码示例

通过一些反射,您可以像这样访问您的dbSet(未经测试的伪代码!):

public object[] QueryDynamicData(string table, int entityId) {    
   //Your DbContext that contains all of your 
   var dbContext = new FooBaa() 
   //Get the DbSet in your DbContext that matches the "Table" name.
   //You are searching for the generic parameter of the DbSet
   var dbSetInfo = dbContext.GetType().GetProperties().FirstOrDefault(e => e.GetGenericArguments().Any(f => f.Name.Equals(table)); 
   //Now get the DbSet from the DbContext and cast it to an IQueryabe
   IQueryable anyDbSet = (IQueryable)dbSetInfo.GetValue(dbContext);
   //Use Dynamic Linq to create a Query that selects an ID
   //warning SQL-Injection possible checkout the 2nd argument of type IDictionary
   return anyDbSet.Where("Id=" + entityId).ToArray();
}

答案 1 :(得分:0)

我在会议之间有几分钟的时间来处理这个问题,并提出了这个问题(将其添加到DbContext课程中:

public dynamic FindEntity(string table, long Id)
{
    PropertyInfo prop = this.GetType().GetProperty(table, BindingFlags.Instance | BindingFlags.Public);
    dynamic dbSet =  prop.GetValue(this, null);
    return dbSet.Find(Id);
}

它使用一些反射来查找DbContext上带有表名的属性,并获取对它的引用。然后它在Find上调用DbSet<T>以查找具有指定主键的对象。由于您不发送任何实际的Type信息,因此必须动态输入所有内容。

您可以这样称呼它:

using (var db = new MyContext())
{
    var e = db.FindEntity("Animals", 1);
}

我无法保证对您有多大帮助,但 会在我的测试设置中返回(动态输入)数据。