C#Dynamic Linq / Queries

时间:2012-10-01 14:34:10

标签: c# linq-to-sql

UPDATE2 我开始更多地使用James建议使用反射并得到一些工作,它将返回基于字符串变量的属性值。我不想把它作为一个答案,但我觉得它可能不是最好的解决方案。这是代码:

DataContext dataBase = new DataContext();
List<string> listOfFields = new List<string>;
List<string> listOfUsers = new List<string>


//strFields and strNames are strings generated from listOfFields and listOfUsers
IEnumerable<myUserData> userInfo = dataBase.ExecuteQuery<myUserData>
                       ("select " + strFields + " from myUserData where user_id                          in (" + strNames + ")");    

foreach(var user in userInfo)
{
    foreach(string field in listOfFields)
    {
        string fieldValue = user.GetType().GetProperty(field).GetValue(user,null).ToString
        Console.WriteLine(fieldValue);
    }

}

更新 我正在取得进步!我认为。这可能是一个非常可怕的解决方案和资源匮乏,我还不确定,但它比我一直得到的空白屏幕更好。现在的问题是找到一种方法来返回值而不是字段名称。这是我的代码:

foreach(string userID in listOfUserIDs)
{
    //dataBase is a Datacontext
    var userInfo = dataBase.myTable
                   .Where("user_id == @0", userID)
                   .Select("New(" + strFields + ")");

    foreach(var user in userInfo)
    {
         Console.WriteLine(user);
    }
}

无论其他字段如何输出{first_name = JOHN,last_name = DOE}等。我希望我能找到一种方法来修改我的Select子句,只选择值。


我是一名新手程序员,特别是对C#以及任何调用数据库的新手。这是我的第一个使用查询和数据库的项目,我遇到了基于动态查询成功返回结果的问题。

我已经成功创建了一个可以检索正确信息的查询,但我对如何访问检索到的特定字段感到困惑。

IEnumerable<myTable> userInfo = dataBase.ExecuteQuery<myTable>
("select " + Fields + " from myTable where userID in                 
(" + userNames + ")");

编辑:请原谅我的错误命名约定,但myTable的类型为:System.Collections.Generic.IEnumerable<DatabaseConnection.myTable>{System.Data.Linq.SqlClient.SqlProvider.OneTimeEnumerable<DatabaseConnection.myTable>} 这只是一个占位符名称,在我的数据库中有一个特定的名称。它位于Tables文件夹XD

myTable的类型为DatabaseConnection。 Fields是我正在查找的一串字段,而userNames是一个由逗号分隔的多个用户名的字符串。 示例:Fields =“firstName,lastName,idNumber”           userNames =“John,Jane,Bob”

我的问题是,是否有可能在我正在返回的对象类型中为每个用户迭代每个字段?我只是这样明确地看到它:

    foreach(var x in userinfo)
{
        Console.Writeline(x.firstName);
}

在我目前的情况下,这不起作用,因为用户可能想要与特定用户名相关的其他字段。

我也尝试过使用Dynamic Linq Library,虽然我能够成功设置我的选择字符串,但我不确定当userID等于几个不同的字符串时如何正确设置我的where子句。 (名称的数量并不总是相同)

var dataInfo = dataBase.myTable
                       .Where("userID == @0", "(" + userIDs + ")")
                       .Select("New(" + fields + ")");

我已经被困在这几天了。任何帮助将不胜感激。也许我认为解决方案太简单了?我觉得我应该可以在我的第一段代码中使用GetProperties()或类似的东西。

如果这个问题得到解答并且我的格式不佳(我在这里发布第一篇文章),我也很抱歉。在我的研究期间,我无法找到我正在寻找的东西,或者我可能只是没有正确理解代码。再次感谢您的帮助!

编辑:所有这些都是我目前正在处理的Excel Addin。我需要将信息放入List或某种形式的对象中,这样我就可以将每个字段结果放入特定的单元格中。

编辑:如果我使用了错误的术语,请原谅。我觉得我的错误可能在我的Enumerable类型中并命名为“myTable”可能会令人困惑。它是从项目中的.dbml文件中的服务器资源管理器中提取的表。

编辑:对每个用户运行查询并检索该用户名的每个请求字段,效率是多么低效/耗时?如果这只是我需要添加一个简单的循环,我会觉得很傻。

4 个答案:

答案 0 :(得分:1)

如果我正确地理解了你的问题并且想要迭代对象的所有属性(不知道它们在编译时是什么),你可以使用Reflection,例如。

foreach (var prop in userInfo.GetType().GetProperties())
{
    Console.WriteLine("Property name: " + prop.Name);
    Console.WriteLine("Property value: " + prop.GetValue(userInfo, null));
}

答案 1 :(得分:1)

因为看起来你只是使用LINQ to SQL,所以只需使用LINQ来查询数据。我将假设您已经创建了一个DataContext模型,并且MyTable是模型中的元素包含某种用户信息。

using (MyDataContext db = new MyDataContext()) {

    var results = (from m in db.MyTable
                   where m.UserId == userId
                   select m);

    // Loop over all of the rows returned by the previous query and do something with it
    foreach (var m in results) {
        // m represents a single row in the results, do something with it.
        Console.WriteLine(m.UserId);
    }

}

或者,如果您希望查询仅返回一行,那么您只需使用SingleSingleOrDefault将结果投影到单个对象中,而不是结果集合:

using (MyDataContext db = new MyDataContext()) {

    var singleResult = (from m in db.MyTable
                        where m.UserId == userId
                        select m).SingleOrDefault();

    // Do something with the single result
    if (singleResult != null) {
        Console.WriteLine(singleResult.UserId);
    }

}

修改

前面的示例处理了有关如何使用LINQ查询兼容数据源的基础知识。大多数LINQ提供程序(例如您使用的LINQ to SQL)都支持IQueryable接口。简短的解释是,此接口允许您动态构建查询,并将该查询的实际执行推迟到您实际尝试访问结果时的最后一分钟。 LINQ查询返回的对象(例如第一个示例中的变量results)返回IQueryable,其中T是您查询的对象类型。它并不是一个与你想象的List<T>相同的集合,其中元素已经存在或被明确添加或删除。在第一个示例中,results实际上没有任何元素,直到foreach循环尝试迭代结果。

要处理您的过滤方案,让我们继续构建results查询,直到它满足您的需求,然后我们会在它完好并准备就绪时执行它。

首先假设您的表单有三个要过滤的字段:名字,姓氏和用户ID。为了简单起见,这些字段只是TextBoxes,如果相应的TextBox中有任何输入,我们知道要按字段进行过滤。我们还假设不需要验证,用户将始终将正确的数据输入过滤器。

using (MyDataContext db = new MyDataContext()) {

    // Build out your base query, which would return everything from MyTable
    var results = (from m in db.MyTable
                   select m);

    // Check each textbox for a value to filter by.  Add the filter to the base
    // query where necessary.    

    if(!string.IsNullOrEmpty(txtUserId.Text)) {
        results = results.Where(x => x.UserId == (int) txtUserId.Text);
    }

    if(!string.IsNullOrEmpty(txtFirstName.Text)) {
        results = results.Where(x => x.FirstName == txtFirstName.Text);
    }

    if(!string.IsNullOrEmpty(txtLastName.Text)) {
        results = results.Where(x => x.LastName == txtLastName.Text);
    }

    // Loop over all of the rows returned by the previous query and do something with it.  
    // THIS is the actual point that the SQL would be generated from the query you've 
    // built and executed against the DB.  The elements returned by `results` 
    // should only meet all of the filters that you the user entered for one or
    // more of the fields.  Not entering any data would have resulted in all rows being
    // returned
    foreach (var m in results) {
        // m represents a single row in the results, do something with it.
        Console.WriteLine(m.UserId);
    }

}

上面的示例非常简单,但它代表了您希望将一定数量的字段和AND放在一起的典型过滤方案。我确信有更优雅的方法来封装构建查询过滤器,但核心概念仍然是相同的。只需使用IQueryable<T>界面并将过滤器表达式链接到它。

这样做只允许您使用AND将谓词链接在一起,并且您不能执行类似“用户ID为6或名称为'John'”的操作。您可以使用System.Linq.Expressions命名空间构建更复杂的表达式来构建LINQ表达式,但这些表达式相对复杂,在大多数情况下都不是必需的。

答案 2 :(得分:0)

虽然我还没有尝试过DataContext(或.NET 4.5),但在4.0中你可以使用动态类直接访问字段:

IEnumerable<dynamic> userInfo = (from user in users
                                 where user.id equals userId
                                 select new { user.name, user.id /*, ...*/ }).ToList();

foreach (dynamic user in userInfo)
{
    Console.WriteLine(user.name);
    Console.WriteLine(user.id);
    //...
}

dynamic表示在运行时解析的类,因此即使在编码时,您看不到显示字段的智能感知,只要它们是正确的,它就会起作用。

答案 3 :(得分:0)

更新后2:

您可以将嵌套的foreach简化为某些linq。类似的东西:

        PropertyInfo[] props = typeof(MyUserData).GetProperties();

        var results = from info in userInfo
                      from p in props
                      where listOfFields.Contains(p.Name)
                      select new
                      {
                          FieldName= p.Name,
                          UserId= info.UserId,
                          FieldValue= p.GetValue(info, null)
                      };

        foreach (var item in results)
        {
            Console.WriteLine("(userId = {0}) {1} = {2}", item.UserId, item.FieldName, item.FieldValue);
        }