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

C# 如何为LINQ查询构建动态FROM子句?,c#,.net,linq,linq-to-entities,entity-framework-4.1,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子句所需的基本列,但其他每个视图都有一些不同的列名 那么,是否可以构建查询,以便在需要时在运行时使用不

我有一个标准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();
}

您可以使用表达式树来构建动态LINQ查询。以下是一个例子:

另一种方法是使用动态LINQ库:

这两种方法在这里都有说明:

本例中的谓词生成器使用表达式树方法


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

只需添加另一层间接寻址:

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);
}
从具有所需名称的方法中检索值:

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

到目前为止,这些只是一些简单的例子。反思打开了一个全新的问题袋。只需从上述示例开始,检查它是否满足您的需求。否则,只需提出一个新问题即可-

这一切都很好,但我想保持它的通用性。如果我添加20个其他视图呢。我不想再多加20个案例陈述。。。如果ViewName发生变化,那么您硬编码的现有3将无法工作…@Willem:switch case是最简单的实现。另一个是字典,或者您可以使用反射来查找具有给定上下文名称的字段或属性。在任何情况下,你都必须通过一个给定的字符串找到一个对象,在这种情况下,你可以通过switch或dict硬编码或者使用反射来找到它。好的,反射听起来更好一些。我真的不想硬编码任何东西。那么,如何使用反射获得正确的视图呢?你能举个例子吗?表达式树看起来是一条路要走,但这会带来很多问题,当你开始引入连接时,可能会变得非常复杂。。。