Search code examples
c#entity-framework-6odata

Query by string name?


Is there a way to query the Entity Framework by the string name of the entity? Currently, I am achieving this by implementing a WCF OData service using Entity Framework. I build the URI and execute it against the DbContext (see my current implementation below). This works for simple entities, but any complex entity with a lot of navigation properties and thousands of records crashes the IIS Worker Process with an Out Of Memory Exception.

Current implementation:

public static IEnumerable<object> GetList(string entityName)
{
    Uri dataAccessURI = New Uri(string.Format("https://MyServer/Service.svc/{0}", entityName))
    result = DbContext.Execute<object>(dataAccessURI , "GET", true);

    return result;
}

I am able to accomplish a save just by entity name, what about querying?

db.AddObject(entityName, record);
db.SaveChanges();

Note: I cannot use Generics. I'd love to be able to use something like

public static DbSet<TEntity> GetList<TEntity>()

but I cannot because the application is only passed the string name of the entity.


Solution

  • DbContext can create a DbSet based on a provided type. And a type can be created from a string. So if you know the name of the entity you should be able to do something like this:

    public static IEnumerable<object> GetList(string entityName)
    {
        Type entityType = Type.GetType(string.format("Namespace.{0}, MyAssembly", entityName);
        DbSet dbSet = DbContext.Set(entityType);
    
        // DbSet implements IEnumerable, so you will be able to safely cast it like so.
        // Or you can assign it to IEnumerable directly.
    
        IEnumerable list = dbSet as IEnumerable;
        return list.Cast<object>.ToList();
    }
    

    It's not the prettiest solution. But it works. I do not know about the performance impact.

    It has the obvious downside that you need to know the namespace of the entity. But as long as all your entities are in the same namespace, such as DataAccess.Models or DataAccess.Entitites, it should work.

    Also note that this will query the entire table and fetch all rows. This may, or may not, be what you want. You might also want to dispose the DbContext somewhere.