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

こ雲淡風輕ζ 提交于 2019-12-05 01:27:04

问题


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();
}

回答1:


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.




回答2:


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. ;-)



来源:https://stackoverflow.com/questions/13796941/how-to-build-a-dynamic-from-clause-for-a-linq-query

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!