【问题标题】:Dynamic query using LINQ to SQL使用 LINQ to SQL 的动态查询
【发布时间】:2012-12-21 11:12:56
【问题描述】:

我需要弄清楚是否可以使用 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>();
    }

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

【问题讨论】:

标签: c# linq dynamic


【解决方案1】:

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

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

【讨论】:

  • 这会给你一个匿名类型,但不是动态结果!
  • 我不能,在项目中我们只能使用LINQ to SQL,是客户的要求之一(它是一个已经存在的应用程序的插件)。
  • 不过,它是一个有用的替代方案 :)
  • @benVG - 然后你需要使用反射从表名中获取表的类型并创建这个对象的实例,据我所知,你不能在 linq 中做到这一点
【解决方案2】:

我找到了一种方法,但我不确定我是否会使用此代码。如果您有一个包含两个表的 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();

【讨论】:

    【解决方案3】:

    我知道这已经过时了,但是如果您像我一样在这里寻找答案,那么也许这会有所帮助。我直接使用 .NET ObjectContext 而不是 DataContext 数据源。如果您使用的是 DataContext 版本,那么您可以简单地(我希望)改用 queryResults = myGlobalContext.ExecuteQuery&lt;dbGenericData&gt;(query).ToList();,我很确定它会以相同的方式工作。

    如果您在命名和设计方面有标准,例如

    ,您的表格将更容易使用
    • 表的 ID 字段始终为 X 类型(INT、GUID 等)
    • ID 字段始终命名为 tableNameID,即带有 ID 标记的“表名”。
    • 等,

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

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

    最后说明:在查询字符串中,您将看到我使用“AS”关键字将 DB 字段转换为新名称。我将“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; }
    
    }
    

    【讨论】:

      【解决方案4】:

      您可以基于T 使用返回DbSet 的通用方法并使用db.Set&lt;T&gt;

      【讨论】:

        【解决方案5】:
        
        var esql = "从 TypeName 中选择 t 作为 t"
        var q = db.CreateQuery(esql);
        
        

        使用实体 sql 进行 linq to sql,http://esql.codeplex.com

        【讨论】:

          猜你喜欢
          • 2011-12-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-07-23
          • 1970-01-01
          • 1970-01-01
          • 2010-12-17
          • 1970-01-01
          相关资源
          最近更新 更多