使用LINQ to SQL进行动态查询

时间:2013-01-07 17:15:59

标签: c# linq dynamic

我需要弄清楚是否可以使用LINQ动态构建查询,动态选择要在其中执行查询的表。

这是我要做的一个例子:

//Not working,just for example

public List<dynamic> _getGenericList(String tableName)
    {
        var l = from a in db.//I need to use here tableName
                  select a;

        return l.ToList<dynamic>();
    }

有没有办法让这成为可能?

5 个答案:

答案 0 :(得分:3)

如果查询很简单,你可以动态创建一个标准的sql语句并执行它,这是最简单的方法,而不使用处理器大量反射和复杂的代码?

var query = "SELECT * FROM " + tableName;
var res = context.ExecuteQuery<dynamic>(query).ToList();

答案 1 :(得分:1)

我找到了一种方法,但我不确定我是否会使用此代码。如果您有一个包含两个表的DataContext:

PrimaryTable 
    ID,
    FirstValue,
    SecondValue

SecondaryTable
    ID,
    FirstSecondaryValue

您可以使用以下DataHelper类:

class DataHelper
{
    public MyDatabaseDataContext db = new MyDatabaseDataContext();

    List<dynamic> GetDynamicList<T>() where T : class
    {
        System.Data.Linq.Table<T> table = db.GetTable<T>();

        var result = from a in table select a;

        return result.ToList<dynamic>();
    }

    public List<dynamic> GetWhatIWant(string tableName)
    {
        Type myClass = Type.GetType("DynamicLinqToSql." + tableName);
        MethodInfo method = typeof(DataHelper).GetMethod("GetDynamicList", BindingFlags.NonPublic | BindingFlags.Instance);
        method = method.MakeGenericMethod(myClass);
        return (List<dynamic>)method.Invoke(this, null);
    }
}

然后,您可以创建DataHelper的实例并调用GetWhatIWant方法,并传入表名。

var dataHelper = new DataHelper();

List<dynamic> myFirstList = dataHelper.GetWhatIWant("PrimaryTable");

for (int i = 0; i < 5 && i < myFirstList.Count; i++)
{
    System.Console.WriteLine(String.Format("{0} - {1}", myFirstList[i].FirstValue.ToString(),  myFirstList[i].SecondValue.ToString()));
}

List<dynamic> mySecondList = dataHelper.GetWhatIWant("SecondaryTable");

for (int i = 0; i < 5 && i < mySecondList.Count; i++)
{
    System.Console.WriteLine(mySecondList[i].FirstSecondaryValue.ToString());
}

System.Console.ReadKey();

答案 2 :(得分:0)

我知道这很古老,但是如果您像我一样在这里寻找答案,那么也许会有所帮助。我直接使用.NET ObjectContext而不是DataContext数据源。如果您使用的是DataContext版本,则可以简单地(我希望)使用queryResults = myGlobalContext.ExecuteQuery<dbGenericData>(query).ToList();来代替,而且我敢肯定它会以相同的方式工作。

如果您具有类似

的命名和设计标准,那么您的表将更易于使用。
  • 表的ID字段始终为X类型(INT,GUID等)
  • “ ID”字段始终命名为“ tableNameID”,即带有“ ID”标记的“表名”。
  • 等,

这将使您可以通过简单地在表名上附加'ID'字符串来轻松构建ID字段,并在需要时使用可靠的CAST。

说到CAST,您会在查询字符串中注意到一个。您将需要使用CAST修改SQL字符串的用法,更改字段长度(例如我的nvarChar(50)示例等),以克服从数据库中获取各种数据类型的问题。

最后的注释:在查询字符串中,您将看到我使用'AS'关键字将数据库字段转换为新名称。我将“ tableIDField”转换为名称“ id”,并将“ requestedField”转换为名称“ dbData”。这允许系统将数据库中的重命名字段匹配到将数据转储到的STRUCT对象容器中。这样,您就可以构造通用容器来保存返回的数据,而不必担心与数据库字段名称匹配。

我不是这方面的专家,但我希望这能帮助到别人。

private void testMethod(string requestedField, string tableName)
{
    var tableIDField = tableName + "ID";

    var query = "select " + tableIDField + " as id, CAST(" + requestedField + "as nvarchar(50)) as dbData from " + tableName;

    List<dbGenericData> queryResults = null;

    try
    {
        queryResults = myGlobalContext.ExecuteStoreQuery<dbGenericData>(query).ToList();
    }
    catch (Exception ex)
    {
        //Simply ignore any exceptions.  
        //These will need examined to determine best solution to unexpected results.
    }
}
private struct dbGenericData
{
    public dbGenericData(int id, string dbData)
    {
        this = new dbGenericData();
        ID = id;
        DBData = dbData;
    }

    public int ID { get; set; }

    public string DBData { get; set; }

}

答案 3 :(得分:-1)

您可以使用Generic Method并使用db.Set<T>返回DbSet基于T

答案 4 :(得分:-2)


var esql = "select t from TypeName as t"
var q = db.CreateQuery(esql);

将实体sql用于linq到sql,http://esql.codeplex.com