Цикл через Active Directory для получения менеджеров и прямых отчетов - PullRequest
1 голос
/ 29 февраля 2012

Полегче со мной, это мой первый вопрос;)

Я потратил много времени на поиски, но не нашел того, что искал.У меня есть инструмент для создания отчетов на основе интрасети (VB.Net + ASP.Net Integrated Windows Authentication), который ищет пользователей и менеджеров из таблицы SQL Server 2005, чтобы свести отчеты к уровню менеджера.

В настоящее время эта таблица ведется вручную, и меня попросили сделать ее более динамичной, поскольку она будет расширена для гораздо большего числа пользователей.Поэтому я ищу связь с Active Directory для создания таблицы Org на внутреннем сервере, которая заменит текущую введенную вручную.

Мне удобно получать пользовательские данные из AD, но не такКонечно, в отношении наилучшего подхода к настройке я подумал о следующей таблице:

CREATE TABLE dbo.Employees
(
    EmpID       nvarchar(8) PRIMARY KEY,
    EmpName     nvarchar(30),
    EmpNo       nvarchar(15),
    EmpEmail    nvarChar(255),
    EmpTitle    nvarchar(255),
    MgrID       nvarchar(8) FOREIGN KEY REFERENCES Employees(EmpID)
)
GO

EmpID будет NetworkID (sAMAccountName).

Тогда это будетнужно заполнить из AD, я думаю, через рекурсивные вызовы, чтобы заполнить поля.

Тогда я не уверен, как структурировать код так, чтобы он охватывал каждого сотрудника каждого менеджера, начиная с определенного уровня.

В настоящее время я использую нижеследующее, чтобы получить прямые отчеты для данного менеджера:

 Public Function GetDirectReports(ByVal ADFullName As String) As ArrayList

            Dim adItems As ArrayList = New ArrayList

            Dim rootEntry As New DirectoryEntry("LDAP://" & ADFullName)

            Dim searcher As New DirectorySearcher(rootEntry)
            searcher.PropertiesToLoad.Add("directReports")
            searcher.PropertiesToLoad.Add("sAMAccountName")
            searcher.PropertiesToLoad.Add("cn")

            searcher.PageSize = 5
            searcher.ServerTimeLimit = New TimeSpan(0, 0, 30)
            searcher.ClientTimeout = New TimeSpan(0, 10, 0)

            Dim queryResults As SearchResultCollection
            queryResults = searcher.FindAll()

            Dim x As Integer

            For Each result As SearchResult In queryResults
                For x = 0 To result.Properties("directReports").Count - 1
                    adItems.Add(New ADReports(result.Properties("directReports")(x), _
                                ExtractUser(result.Properties("directReports")(x))))
                Next
            Next
            Return adItems
        End Function

        Private Function ExtractUser(ByVal username) As String
            Return Split(Split(username, "CN=")(1), ",")(0)
        End Function

Любые комментарии, предложения и помощь будут очень благодарны :)

Ответы [ 2 ]

1 голос
/ 18 декабря 2014

Вы можете использовать этот фрагмент кода, чтобы получить имя менеджера для определенного сотрудника.Если вы хотите знать подчиненных менеджера, то, пожалуйста, замените прямые отчеты менеджером.

    lblUser.Text = My.User.Name
    Dim _UserName As String = GetDomainUserName(My.User.Name)
    Dim context As PrincipalContext = New PrincipalContext(ContextType.Domain)


    ' find a user
    Dim user As UserPrincipal = UserPrincipal.FindByIdentity(context, lblUser.Text)

    Dim allUsers As New ArrayList()
    Dim searchRoot As New DirectoryEntry("LDAP://DOMAIN")
    Dim search As New DirectorySearcher(searchRoot)
    'search.Filter = "(&(objectClass=user)(manager=" + user.DistinguishedName + "))"
    search.Filter = "(&(objectClass=user)(directReports=" + user.DistinguishedName + "))"
    search.PropertiesToLoad.Add("samaccountname")

    Dim result As SearchResult
    Dim resultCol As SearchResultCollection = search.FindAll()
    If resultCol IsNot Nothing Then
        For counter As Integer = 0 To resultCol.Count - 1
            result = resultCol(counter)
            If result.Properties.Contains("samaccountname") Then
                allUsers.Add(DirectCast(result.Properties("samaccountname")(0), [String]))
            End If
        Next
    End If
1 голос
/ 29 февраля 2012

По сути, я бы просто просмотрел всю AD, вытащил всех пользователей с необходимой информацией и сохранил их на SQL Server.При перечислении не беспокойтесь и не заботьтесь об иерархиях - вы будете обращаться с ними позже.

Как только данные окажутся внутри SQL Server, вы можете создать, например, рекурсивное CTE (Common Table Expression), чтобы получитьиерархия сотрудников - кто отчитывается перед кем и т. д.

В качестве дополнительного примечания: sAMAccountName не гарантирует стабильной работы - он может измениться (редко, но возможно) - поэтому, возможно, вам нужен другой элементкак уникальный идентификатор для каждого пользователя?Использует ли ваша компания атрибут userID или что-то еще?Или вы можете использовать GUID пользователя AD (который останется прежним) вместо samAccountName?

Также: если вы решите придерживаться sAMAccountName: имейте в виду, что это может быть до 20длинных символов - NVARCHAR(8) будет недостаточно.Кроме того: вам действительно нужны строки Unicode?Они всегда вдвое длиннее, чем строки не-Unicode VARCHAR(20) - просто спросите, вам это может понадобиться, тогда это нормально.

Вероятно, я бы добавил в таблицу искусственный столбец EmployeeID (INT IDENTITY) для обработки всех требований к хорошему ключу кластеризации в этой таблице: уникальный, стабильный, узкий.nvarchar(20) - это, прежде всего, переменная длина, которая не очень хороша, и может иметь длину до 40 байт, что опять-таки не оптимально.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...