13

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

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

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

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

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

如果这个问题已经得到解答并且我的格式很差(这里的第一篇文章),我也很抱歉。在我的研究过程中,我无法找到我正在寻找的东西,或者我可能只是没有正确理解代码。再次感谢任何帮助!

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

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

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

4

4 回答 4

1

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

foreach (var prop in userInfo.GetType().GetProperties())
{
    Console.WriteLine("Property name: " + prop.Name);
    Console.WriteLine("Property value: " + prop.GetValue(userInfo, null));
}
于 2012-10-01T14:41:45.907 回答
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 是您查询的对象的类型。它与您可能想到的 a 的意义不同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);
    }

}

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

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

于 2012-10-01T16:49:08.157 回答
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 表示一个在运行时解析的类,因此即使在编码时看不到智能感知显示字段,只要它们正确,它就会起作用。

于 2012-10-09T09:25:29.147 回答
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);
        }
于 2012-10-29T12:24:09.677 回答