如何为LINQ查询构建动态FROM子句?

时间:2012-12-10 07:54:04

标签: c# .net linq linq-to-entities entity-framework-4.1

我有一个标准的LINQ查询:

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

我想知道是否可以构建动态LINQ查询,以便我可以在运行时更改SomeDataContext.ViewName

我有大约5个不同的视图,都有执行where子句所需的基本列,但每个其他视图都有一些不同的列名。

那么是否可以构建查询以便在需要时可以在运行时使用不同的上下文?

示例:

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

2 个答案:

答案 0 :(得分:6)

您可以使用表达式树来构建动态LINQ查询。以下是一个示例:http://msdn.microsoft.com/en-us/library/bb882637.aspx

另一种方法是使用Dynamic LINQ库: http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

这两种方法都在这里说明: http://www.codeproject.com/Articles/231706/Dynamic-query-with-Linq

此示例中的Predicate Builder使用表达式树方法。

通常,动态LINQ更容易实现,但表达式树更加类型安全。

答案 1 :(得分:3)

只需添加另一层间接:

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

有关如何使用反射的更新

从具有所需名称的字段中检索值:

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

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

从具有所需名称的属性中检索值:

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

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

从具有所需名称的方法中检索值:

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

到目前为止,这只是一些简单的例子。反思开启了一整套问题和问题。只需从上面的例子开始,检查它是否符合您的愿望。否则只需回来一个新问题。 ; - )