Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to build a dynamic FROM clause for a LINQ query?

I have a standard LINQ query:

var list = from x in SomeDataContext.ViewName
           where //Rest of where clause
           select x;

I would like to know if it is possible to build a dynamic LINQ query so that i can change the SomeDataContext.ViewName at runtime.

I have about 5 different views, all with the basic columns needed to perform the where clause, but with some different column names for each of other views.

So is it possible to build up the query so that i can use the different context at runtime, when needed?

Example:

public void SomeMethod()
{
    var listA = GetList("DataContext.ViewA");
    var listB = GetList("DataContext.ViewB");
    var listC = GetList("DataContext.ViewC");
}

public List<EntityObject> GetList(string dataContextName)
{
    return (from x in /*HERE I WANT TO USE THE dataContextName*/
           where //Rest of where clause
           select x).ToList();
}
like image 820
Willem Avatar asked Dec 10 '12 07:12

Willem


2 Answers

You can use Expression Trees to build dynamic LINQ queries. Here is an example: http://msdn.microsoft.com/en-us/library/bb882637.aspx

Another approach is to use Dynamic LINQ library: http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

Both approaches are illustrated here: http://www.codeproject.com/Articles/231706/Dynamic-query-with-Linq

Predicate Builder from this example uses Expression Tree approach.

In general, Dynamic LINQ is easier to implement but Expression Tree is more type-safe.

like image 148
vladich Avatar answered Sep 22 '22 01:09

vladich


Just add another layer of indirection:

public void SomeMethod()
{
    var listA = GetList("DataContext.ViewA");
    var listB = GetList("DataContext.ViewB");
    var listC = GetList("DataContext.ViewC");
}

public List<EntityObject> GetList(string dataContextName)
{
    return (from x in GetSpecificSource(dataContextName)
           where //Rest of where clause
           select x).ToList();
}

public IEnumerable<MyType> GetSpecificSource(string dataContextName)
// Or: public IQueryable<MyType> GetSpecificSource(string dataContextName)
{
    // ToDo: Return the correct source depending on the name. E.g.:
    switch(dataContextName)
    {
        case "DataContext.ViewA":
            return DataContext.ViewA;
        case "DataContext.ViewB":
            return DataContext.ViewB;
        case "DataContext.ViewC":
            return DataContext.ViewC;
    }
}

Update on how to use reflection

Retrieve a value from a field with a desired name:

var fieldName = "ViewA";
var fieldFound = type.GetField(fieldName, BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

if(fieldFound != null)
{
    return fieldFound.GetValue(instance);
}

Retrieve a value from a property with a desired name:

var propertyName = "ViewA";
var propertyFound = type.GetProperty(propertyName, BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

if(propertyFound != null)
{
    return propertyFound.GetValue(instance, null);
}

Retrieve a value from a method with a desired name:

var methodName = "ViewA";
var methodFound = type.GetMethod(methodName, BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

if(methodFound != null)
   && methodFound.GetParameters().Length == 0)
{
    return methodFound.Invoke(instance, null);
}

So far these are just some simple examples. Reflection opens up a complete new bag of issues and questions. Simply start with the above examples and check if it meets your desires. Otherwise simply come back with a new question. ;-)

like image 32
Oliver Avatar answered Sep 24 '22 01:09

Oliver