【问题标题】:LINQ query help please, for each works?请帮助LINQ查询,每个作品?
【发布时间】:2013-09-28 10:48:34
【问题描述】:

我遇到了一些无法在 LINQ 中运行的代码的问题,但它确实可以作为简单的 for..each 运行。任何解释和解决方案将不胜感激。

我有 3 个类,用户、用户、用户权限组成如下:

班级用户

ObservableCollection<User> GetList

班级用户

Public int id  {get;set;}
Public string UserName  {get;set;}
Public UserPermissions Permissions {get;set;}

类用户权限

Public Int ID {get;set;}
Public int ApplicationID {get;set;}

这有效并返回正确的用户:

Users users = new Users();
foreach (User u in users.GetList() )
{
    if (u.UserName==username && u.Permissions.ApplicationID == applicationId)
    {
        usr = u;
        break;
    }
}

下面的 linq '应该' 做同样的事情,但事实并非如此。输出窗口中没有返回或引发错误,并且 muser 变量在跨过它之后根本不存在。我尝试在我的演员表中更具体并使用 AsQueryable。我什至尝试使用两个 from 命令让 p=u.Permissions,但似乎没有任何解决方法。

我担心我的其他类会因此受到影响,并在以后使用更复杂的查询时引起问题。

var  musers = from Users.User u in UsersList
               where (u.UserName==userName) 
                       && (u.Permissions.ApplicationID == ApplicationId)
              select u.ID;

还有一点信息是以下错误吗?

var t1 = UsersList.SelectMany(u => u.Permissions);

错误 1 ​​无法从用法中推断方法“System.Linq.Enumerable.SelectMany(System.Collections.Generic.IEnumerable, System.Func>)”的类型参数。尝试明确指定类型参数。

【问题讨论】:

  • musers 在你迭代它之前不会有任何东西(许多 linq 方法被推迟到你迭代可枚举的点)。试试var id = musers.FirstOrDefault();,如果枚举为空,这将返回default(T)。如果你想测试空,试试if (musers.Any()) { }
  • 扩展方法?例如:UserList.Where(x=>x.UserName == userName && x.Permissions.ApplicationID == ApplicationId).Select(x=>x);或 UserList.Select(x=>x.UserName == userName && x.Permissions.ApplicationID == ApplicationId)
  • 已经试过这个亚历克斯,复制并粘贴你的例子,结果和我的代码一样,我害怕。但感谢您的尝试。
  • @AlexDenysenko 查询语法被编译成那个,虽然你刚刚写的代码不是很正确,但如果它是正确的,使用该语法不会发生任何变化。跨度>
  • @user1284624 在列表名称后添加AsEnumerable。目前,您的“工作”代码示例正在应用程序端执行所有过滤,linq 示例正在使用查询提供程序在它到达之前执行它,这可能有问题。如果使用AsEnumerable 有效,则可能意味着查询提供程序无法将表达式转换为查询。您在这里使用什么查询提供程序?

标签: c# linq .net-3.5


【解决方案1】:
        var usr = users.GetList()
            .FirstOrDefault(
                p => p.UserName == username 
                    && p.Permissions.ApplicationID == applicationId);

应该为你做。如果没有找到用户,FirstOrDefault 可以返回 null...

【讨论】:

  • 到目前为止,没有任何建议可以解决问题,尽管它们都应该有效。我应该指定该集合在我的控制之下,并且正确填充了基础和所有子级。所以 FirstOrDefault 不是必需的。但感谢您到目前为止的帮助。
  • hmmm 我刚刚注意到一些事情: p => p.UserName == userName && p.Permissions.ApplicationID == applicationId p.UserName 有 linq 扩展,但 p.Permissions.ApplicationID 没有?这有意义吗?
  • 我只是创建了一个控制台应用程序,其中包含您的代码,您的外观和我的 FirstOrDefault 都可以正常工作...如果您愿意,我可以发布代码。如果这对您不起作用,则似乎还有其他问题
  • 当我尝试 SelectMany 时出现以下错误,表明 Permissions 对象存在某种可枚举错误,不是吗? var t1 = UsersList.SelectMany(u => u.Permissions);错误 1 ​​方法的类型参数 'System.Linq.Enumerable.SelectMany(System.Collections.Generic.IEnumerable, System.Func >)' 不能从用法中推断出来。尝试明确指定类型参数。 C:\Workspace\Users\Users.cs 131 30 个用户
【解决方案2】:

亚当在场,谢谢亚当。

我在调试器中看到 'var found=from...' 表明 found 已创建并在运行 linq 语句的位置包含一个值。但是,正如 Adam 正确指出的那样,linq 枚举被推迟到您枚举查询的那一点。对我来说一切都很好的原因是,直接在有效的代码下面是一个 for 循环,它触发 THAT linq 查询的枚举。上面的其他人都没有这样的枚举,就好像他们默默地失败了一样!

我认为编译器正在优化该函数,以便我可以在代码中的位置而不是在枚举发生的位置调试 linq 查询,这是一个不错的技巧,但它完全错了!哈哈。这让我觉得查询本身在某种程度上被评估了,即使在您使用 ToList()、Count() 或其他枚举函数之前结果不可用。

例如,在下面的代码中,只有 f3 将包含任何内容,其他的只是,嗯,什么都没有,因为它们从未被枚举!

var f1 = from .....;

var f2 = 来自 ....;

var f3 = 来自 ....;

做很多其他的事情,甚至调用一个函数

int count = f3.Count();

有趣的是 f1, f2 即使在行运行之后也没有,但 f3 在枚举 (Count) 发生之后和之前都有一个值,所以我认为编译器优化/调试在这里发挥了作用。

希望这对其他人有帮助:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-18
    相关资源
    最近更新 更多