简体   繁体   中英

Dynamic query using LINQ to SQL

I need to figure out if it is possible to dynamically build a query with LINQ, dynamically selecting the table in which to perform the query.

This is an example of what I would do:

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

Is there a way to make this possible?

If the query is this simple you can dynamically create a standard sql statement and execute it, this is the most simplest way without using processor heavy reflection and complex code?

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

I've found a way to do it, but I'm not sure if I'd use this code. If you have a DataContext that contains two tables:

PrimaryTable 
    ID,
    FirstValue,
    SecondValue

SecondaryTable
    ID,
    FirstSecondaryValue

You could use the following DataHelper class:

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

Then you can create an instance of your DataHelper and call the GetWhatIWant method, passing in the table name.

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

I know this is old, but if you are here looking for answers like I was, then maybe this will help. I'm using a .NET ObjectContext directly instead of a DataContext data source. If you are using the DataContext version then you can simply (I hope) use queryResults = myGlobalContext.ExecuteQuery<dbGenericData>(query).ToList(); instead and I'm pretty sure it will work the same way.

Your tables will be a lot easier to work with if you have standards in naming and design like

  • the ID field for the table is always X type (INT, GUID, etc)
  • the ID field is always named tableNameID, the 'table name' with ID tagged on.
  • etc,

This will allow you to easily build the ID field by simply appending the 'ID' string onto the table name and will allow you to use a reliable CAST, if needed.

Speaking of CAST you will notice one in the query string. You will need to modify the use of the SQL string using CAST, changing field lengths like my nvarChar(50) example, etc, to overcome getting various TYPES of data from your database.

Final note: In the query string you will see I use the 'AS' key word to cast the DB field to a new name. I cast the 'tableIDField' into the name 'id' and I cast the 'requestedField' into the name 'dbData'. This allows the system to match up the renamed fields from the DB into the STRUCT object container we dump the data into. This allows you to construct generic containers to hold the data returned without having to worry about matching up with the DB field names.

I'm not a guru at this stuff, but I hope this helps somebody out.

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

}

您可以使用通用方法并使用db.Set<T>返回基于TDbSet

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

Use entity sql for linq to sql, http://esql.codeplex.com

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM