2

我想创建一个排序的用户列表,这些用户出现在一个数据表“StatsTable”中。

我需要从 StatsTable 中获取用户 ID,然后使用它在另一个数据表“UserTable”中查找用户名。当我有这些时,我想让 userID 成为 Key 并且 UserName 成为排序列表中的 Value。

我设法获取了用户 ID 并将其添加到排序列表中,但用户名以“System.Data.EnumerableRowCollection`1[System.String]”的形式出现。

我究竟做错了什么?谢谢你的帮助。

    SortedList UserList = new SortedList();

    List<double> listofUserIDs = StatsTable.AsEnumerable()
    .Select(uid => uid.Field<double>("UserID")).ToList<double>();
    foreach (double UID in listofUserIDs)
    {
        string userName = UserTable.AsEnumerable()
            .Where(id => double.Equals(id.Field<double>("UserID"), UID))
        .Select(name => name.Field<string>("First_Name") + " " + name.Field<string>("Last_Name")).ToString();

         UserList[UID] = userName;
    }
4

4 回答 4

4

首先,我会避免使用double任何需要平等的东西。字符串、GUID 和整数都适用于 ID - 双精度数,不是那么多。

其次,我会将所有这些都作为 LINQ 中的一个连接来完成——你真的不需要每次都迭代每一个项目。您正在将 O(N+M) 操作转换为 O(N + M * N) 操作。

第三,您的查询不起作用的原因是您只是投影到一系列字符串。你可能碰巧知道会有一个匹配,但你需要告诉计算机。调用ToString()一个序列不会给你任何有用的东西。例如,您可以使用Single()or SingleOrDefault()

string userName = UserTable.AsEnumerable()
    .Where(id => double.Equals(id.Field<double>("UserID"), UID))
    .Select(name => name.Field<string>("First_Name") + " "
                  + name.Field<string>("Last_Name"))
    .Single();

一旦你使用Single()(或任何其他返回单个值的调用)你根本不需要ToString(),因为结果已经是一个字符串。

使用Single(),如果不完全是一个结果,将引发异常。使用SingleOrDefault(),如果有多个结果,仍然会抛出异常,但如果没有结果,你只会得到一个null引用。如果只有一个结果以外的任何内容都是错误的,则应使用Single().

于 2012-12-19T11:09:11.197 回答
4

您应该使用Enumerable.Join链接两个表并选择您需要的内容。在这种情况下,我会使用 aTuple<int, string>而 theint是 UserID(带有小数位的 UserID 没有意义,是吗?)并且字符串是用户名:

var query = from rStats in StatsTable.AsEnumerable()
            join rUser in UserTable.AsEnumerable()
            on rStats.Field<int>("UserID") equals rUser.Field<int>("UserID")
            select new {
                UserID   = rStats.Field<int>("UserID"), 
                UserName = string.Format("{0} {1}"
                               , rUser.Field<string>("First_Name")
                               , rUser.Field<string>("Last_Name"))
            };

List<Tuple<int, string>> users = query
    .OrderBy(u => u.UserName)
    .Select(u => Tuple.Create(u.UserID, u.UserName))
    .ToList();

您可以通过Item属性访问元组:

foreach(var user in users)
    Console.WriteLine("UserID:{0} UserName:{1}",user.Item1,user.Item2);
于 2012-12-19T11:14:33.087 回答
2

这是因为您正在使用.AsEnumerable()which 返回通常返回列表的类型的源。您可以使用 ) 将其作为列表返回.ToList<string>(并选择第一条记录,也可以使用FirstOrDefault(); 而不是.ToList<string>()返回第一条记录。

于 2012-12-19T11:09:13.973 回答
1

代码应如下所示:

SortedList UserList = new SortedList();

List<double> listofUserIDs = StatsTable.AsEnumerable()
.Select(uid => uid.Field<double>("UserID")).ToList<double>();
foreach (double UID in listofUserIDs)
{
    string userName = UserTable.AsEnumerable()
        .Where(id => double.Equals(id.Field<double>("UserID"), UID))
    .Select(name => name.Field<string>("First_Name") + " " + name.Field<string>("Last_Name")).FirstOrDefault().ToString();

     UserList[UID] = userName;
}

你应该添加FirstOrDefault()before ToString(),因为 select 会给你一个新的枚举,而不是一个对象!。

于 2012-12-19T11:07:53.413 回答