没有使用数据表c#上的查询表达式获取预期数据

时间:2012-12-19 11:03:19

标签: c# linq datatable

我想创建一个显示在一个数据表“StatsTable”中的用户的排序列表。

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

我设法获取userID并将其添加到排序列表中,但userName以“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 个答案:

答案 0 :(得分:4)

首先,我会避免将double用于任何需要平等的事情。字符串,GUID和整数都适用于ID - 双倍,而不是。

其次,我将所有这些作为LINQ中的联接 - 您实际上不需要每次都迭代每个项目。您正在将O(N + M)操作转换为O(N + M * N)操作。

第三,您的查询无效的原因是您只是投射到字符串的序列。您可能碰巧知道将只有一个匹配,但您需要告诉计算机。在序列上调用ToString()不会给你任何有用的东西。例如,您可以使用Single()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()

答案 1 :(得分:4)

您应该使用Enumerable.Join链接两个表并选择所需内容。在这种情况下,我会使用Tuple<int, string>,而int是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);

答案 2 :(得分:2)

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

答案 3 :(得分: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()之前添加ToString(),因为,select会为您提供一个新的可枚举,而不是一个对象!