快速在Enumerable对象中查找结果 [英] Finding results in a Enumerable object quickly

查看:139
本文介绍了快速在Enumerable对象中查找结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个实用程序,以查看用户自从我存储在数据库中的日期以来是否已经登录到Windows.

I am trying to write a utility to see if a user has logged in to windows since a date that I have stored in a database.

private void bwFindDates_DoWork(object sender, DoWorkEventArgs e)
{
    UserPrincipal u = new UserPrincipal(context);
    u.SamAccountName = "WebLogin*";
    PrincipalSearcher ps = new PrincipalSearcher(u);
    var result = ps.FindAll();
    foreach (WebAccess.WebLoginUsersRow usr in webAccess.WebLoginUsers)
    {
        UserPrincipal b = (UserPrincipal)result.
            Single((a) => a.SamAccountName == usr.WEBUSER);
        if (b.LastLogon.HasValue)
        {
            if (b.LastLogon.Value < usr.MODIFYDATE)
                usr.LastLogin = "Never";
            else
                usr.LastLogin = b.LastLogon.Value.ToShortDateString();
        }
        else
        {
            usr.LastLogin = "Never";
        }
    }
}

但是性能非常慢.我要从的用户列表中有大约150个Windows用户,因此当我点击UserPrincipal b = (UserPrincipal)result.Single((a) => a.SamAccountName == usr.CONVUSER);行时,每个用户需要10到15秒才能完成操作(逐步执行,我可以看到它正在执行步骤a.SamAccountName == usr.CONVUSE对每个人来说,最坏的情况是运行O(n ^ 2)次)

However the performance is very slow. The user list I am pulling from has about 150 Windows users, so when I hit the line UserPrincipal b = (UserPrincipal)result.Single((a) => a.SamAccountName == usr.CONVUSER); it takes 10 to 15 seconds for it to complete per user (stepping through i can see it is doing the step a.SamAccountName == usr.CONVUSE is run for every person so the worst case is running O(n^2) times)

关于提高效率的任何建议吗?

Any recommendations on ways to improve my efficiency?

推荐答案

令人惊讶的是,Single()在这么小的列表上花了这么长时间.我必须相信这里还有其他事情.对ps.FindAll()的调用可能返回一个不缓存其结果的对象,并迫使您在Single()内的每次迭代中对某些资源进行昂贵的调用.

It's surprising that Single() should take quite so long on such a small list. I have to believe something else is going on here. The call to ps.FindAll() may be returning an object that does not cache it's results, and is forcing you to make an expensive call to some resource on each iteration within Single().

您可能希望使用探查器来调查到达该行时的时间.我还建议您查看FIndAll()的实现,因为它返回的迭代开销非常高.

You may want to use a profiler to investigate where time is going when you hit that line. I would also suggest looking at the implementation of FIndAll() because it's returning something unusually expensive to iterate over.

因此,在仔细阅读了一些代码之后,就可以理解为什么Single()如此昂贵. PrincipalSearcher类使用目录服务存储作为要搜索的存储库. 它不会缓存这些结果.那就是影响您表现的原因.

So after reading your code a little more closely, it makes sense why Single() is so expensive. The PrincipalSearcher class uses the directory services store as the repository against which to search. It does not cache these results. That's what's affecting your performance.

您可能想使用ToList()ToDictionary()来实现该列表,以便在本地访问主要信息.

You probably want to materialize the list using either ToList() or ToDictionary() so that accessing the principal information happens locally.

您还可以完全避免使用此类代码,并使用 FindOne() 方法代替,它使您可以直接查询所需的主体.

You could also avoid this kind of code entirely, and use the FindOne() method instead, which allows you to query directly for the principal you want.

但是,如果您不能使用它,那么类似的方法应该会更好地工作:

But if you can't use that, then something like this should work better:

result.ToDictionary(u => u.SamAccountName)[usr.WEBUSER]

这篇关于快速在Enumerable对象中查找结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆