Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Query an Entity Framework entity without knowing the object type (class/table) in advance

I'm wondering, if it's even possible in the first place, how I would go about querying the database (using EF) using an ID and a table name.

For example, writing a function as:

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

And could be called like:

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

To clarify, this is for a MVC ASP.Net project using Entity Frameworks.

Thanks in advance!

EDIT:

Following the example from @JPVenson, I came up with the following code. Note that it returns a list of Dictionaries, even though Id is unique, since I'm thinking ahead to when we may want to get all results for a dynamic table instead of just by Id. (This is only proof of concept level)

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;
    }
like image 356
Geordie Buch-Frohlich Avatar asked Sep 18 '17 17:09

Geordie Buch-Frohlich


People also ask

How do I write a query in Entity Framework?

Use the DbSet. SqlQuery() method to write raw SQL queries which return entity instances. The resulted entities will be tracked by the context, as if they were returned by the LINQ query.

Is it possible Entity Framework will support table without primary key?

The Entity framework will not support to have a table without primary key, but we can overcome this issue by accessing the table with additional column via a view and marking the new column as Primary in entity framework. Entity Framework requires primary keys for entities.


1 Answers

Yes you can. There is a blog from ScottGu

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

(MS Version of DynamicLinq https://github.com/kahanu/System.Linq.Dynamic/wiki)

that contains the wiki for a lib called DynamicLinq. I'm using it currently in a Project and it will fit your approach.

You still have to wrap it and use some Reflection to build a proper IQueryable but it does a lot of work for you

Edit Code Example

With some reflection you can access your dbSet like this (Untested Pseudocode!):

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();
}
like image 65
Venson Avatar answered Oct 19 '22 21:10

Venson