This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Designer - SQL Database Import not Updating UNSAccountB

Gurus,

I eluded to this question in a previous post and despite my best efforts, I can't find a solution yet. So here is the situation, one of the applications we are attesting to runs off an MS SQL Database and our DBAs have basically given the Quest account rights to run a few stored processes so that it can synch the users/groups from the SQL application to Quest. The script basically opens a connection string to the database, runs the stored procs and uses the data to populate users (one script) and populate data base roles (other script) into UNSAccountB and UNSGroupB respectively while tagging XProxyContext to be the application name... lets call it DBApp1 for privacy.

In the Production environment, the sccripts work just fine... they pull the data in and populate accordingly. I used the Database Transport tool to import all Change Labels into the Test lab. After verifying that AD synch was working Dev and then making sure that Manager > Unified Namespace has an entry for DBApp1, I ran the import. I watched the job logs intently - refreshing every few seconds, just to make sure everything worked. Yay! The script completed and I got NO errors. I even have the script writing a log file to show me what it does. The log file shows several new inserts into the database. Yay!

THEN... I checked UNSAccountB and UNSGroupB. NOTHING is there... There are no records at all...

I tried the same process again with DBApp2. Again, all things look great! Imports run and NOTHING in UNSAccountB or UNSGroupB. What the heck happened? Where did this stuff go? If the logs think everything is fine and the database is sending data (I verified this). Why doesn't it populate into Quest? Can anyone provide me some insight?

Thanks in advance!

  • Okay guys, we were able to solve the issue with DBApp2. Now I am having a similar issue with DBApp1. It's a weird one. The UNSContainerB on this one simply holds an OU for Groups and Users. The actual roles are stored as system entitlements. I have verified that this works properly. However, the users are not being populated at all. There is an OU for Users but nothing is in there. They also don't appear at the root of the DBapp1 Namespace. Not sure what caused this issue. Below is the sanitized import script for users, please advise if you see anything funky.

    #If Not SCRIPTDEBUGGER Then

    References VI.DataImport.dll

    Imports System.Collections.Generic

    Imports System.IO

    Imports System.Globalization

    Imports VI.DB.Specialized

    Imports VI.DataImport

    #End If

    Public Sub TEST_DBApp1_User_Import(ByVal dfImport As DataFileImport)

        ' Standard variables

        Dim logSection As IDisposable

        Dim f As ISqlFormatter = Connection.SqlFormatter

        ' Table

        Dim table As TableDef = Connection.Tables("UNSAccountB")

              Dim logFile As String = Connection.GetConfigParm("Custom\LogFileOutputDirectory") & "\TST_DBApp1_User_CSVImport_" & Year(Now) & Day(Now) & Hour(Now) & Minute(Now) & Second(Now) & ".log"

              ' Do not delete any objects, if this marker is set

              Dim doNotDelete As Boolean = False

              Dim obj As ISingleDbObject = Nothing

              ' Line counter

        Dim counter As New LineCounter()

              ' Value provider

              Dim lineData As New LineValueProvider(New String() {"UserName", "", ""})

              Provider = lineData

              ' Import from an external database

              Dim lineProvider As New DbLineProvider()

              lineProvider.ProviderName = "System.Data.SqlClient.SqlClientFactory, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"

              lineProvider.ConnectionString = Connection.GetConfigParm("Custom\DBApp1\ConnectionString")

              ' SQL statement

              Dim statement As New PlainSqlStatement()

              statement.Statement = "USE [DB1] " & _

    "DECLARE          @return_value int " & _

    "EXEC          @return_value = [dbo].[usp_DBApp1TESTAudit_UserList] " & _

    "SELECT          'Return Value' = @return_value " & _

    ""

     

              lineProvider.Statement = statement

     

              '

        ' Configure column resolution

              '

     

        ' Column indices

        Const iAccountName As Integer = 0

              ' Resolver to get column data from import data

        Dim columnAccountName As IResolveImportValue = New ResolveImportValueSimple("AccountName")

              ' Build a dictionary: The last parameter forces exceptions when duplicate keys are found

        Dim columnUID_Person As New ResolveImportValueHashed( _

            Connection, _

            ObjectWalker.ColDefs(table, "FK(UID_Person).CentralAccount"), False)

              ' Build a dictionary: The last parameter forces exceptions when duplicate keys are found

        Dim columnUID_UNSContainerB As New ResolveImportValueHashed( _

            Connection, _

            ObjectWalker.ColDefs(table, "FK(UID_UNSContainerB).CanonicalName"), False)

              ' Set connection variables

              Connection.Variables("FULLSYNC") = "true"

        Try

            '

            ' Create a dictionary for the destination table

            '

            Dim colImport As IColDbObject = Connection.CreateCol("UNSAccountB")

            Dim elemsByKey As New Dictionary(Of String, IColElem)(StringComparer.OrdinalIgnoreCase)

                        logSection = dfImport.LogSection(#LD("Bilde Index über bestehende Daten")#)

                        Try

                                  ' Set keys and values as display items to load them with the collection

                                  colImport.Prototype("AccountName").IsDisplayItem = True

                                  colImport.Prototype("UID_Person").IsDisplayItem = True

                                  colImport.Prototype("UID_UNSContainerB").IsDisplayItem = True

                                  colImport.Prototype.WhereClause = "xproxycontext = N'DBApp1'"

     

                                  ' Load the collection

                                  colImport.Load(CollectionLoadType.Slim)

                                  ' Put the entries in the dictionary

                                  For Each elem As IColElem In colImport

                                            Dim key As String

                                            key = elem.GetValue("AccountName").String

                                            If elemsByKey.ContainsKey(key) Then

                                                      dfImport.Log(MsgSeverity.Serious, #LD("Duplicate key: {0}", key)#)

                                            Else

                                                      elemsByKey.Add(key, elem)

                                            End If

                                  Next

            Finally

                If Not logSection Is Nothing Then

                                            logSection.Dispose()

                                            logSection = Nothing

                                  End If

            End Try

                        VID_Write2Log(logFile,String.Format("Got {0} existing UNSAccountB records", elemsByKey.Count))

                        logSection = dfImport.LogSection(#LD("Import data from file")#)

            Try

                                  For Each line As Line In lineProvider.GetLines(counter)

                                            ' Pay attention to the Stop flag

                                            If StopProcessing Then

                                                      dfImport.Log(MsgSeverity.Warning, #LD("Abarbeitung wurde gestoppt.")#)

                                                      Exit For

                                            End If

     

                                            Try

                                                      ' Get raw data from the current line

                                                      Dim key As String

                                                      Dim valAccountName As String

                                                      Dim resAccountName As String

                                                      Dim valUID_Person As String

                                                      Dim resUID_Person As String

                                                      Dim valUID_UNSContainerB As String

                                                      Dim resUID_UNSContainerB As String

                                                                valAccountName = line.GetValue(iAccountName)

                                                                valUID_UNSContainerB = "DBApp1/Users"

                                                                '

                                                                ' Here is the place to check and change raw data

                                                                '

                                                                lineData.Line = line

     

                                                                Value = valAccountName

                                                                VID_Write2Log(logFile,String.Format("Read {0} account name from file", valAccountName))

                                                                ' Start of convert script for AccountName

                                                                Value = CStr(Value).Split("\"C)(1).Trim

                                                                ' End of convert script for AccountName

     

                                                                valAccountName = DbVal.ConvertTo(Of String)(Value)

     

                                                                Value = valUID_Person

     

                                                                ' Start of convert script for UID_Person

                                                                Value = CStr(GetValue("0").String).Split("\"C)(1).Trim

                                                                ' End of convert script for UID_Person

     

                                                                valUID_Person = DbVal.ConvertTo(Of String)(Value)

     

     

                                                                ' Convert raw data to final column data values

                                                                resAccountName = DbVal.ConvertTo(Of String)(columnAccountName.ResolveValue(valAccountName), lineProvider.Culture)

                                                                resUID_Person = DbVal.ConvertTo(Of String)(columnUID_Person.ResolveValue(valUID_Person), lineProvider.Culture)

                                                                resUID_UNSContainerB = DbVal.ConvertTo(Of String)(columnUID_UNSContainerB.ResolveValue(valUID_UNSContainerB), lineProvider.Culture)

                                                                resUID_Person = Connection.GetSingleProperty("Person","UID_Person", _

                                                                   f.Comparison("Centralaccount",valUID_Person,ValType.String))

                                                                VID_Write2Log(logFile,String.Format("resUID_Person {0}, valAccountName {1}, resAccountName {2}, valUID_Person {3}", resUID_Person,valAccountName,resAccountName,valUID_Person))

                                                                '

                                                                ' Here is the place to check and change final column data

                                                                '

                                                                '

                                                                ' Here starts the standard handling. It is recommended to not change anything beyond this point.

                                                                '

                                                                '

                                                                ' Create key for this line

                                                                '

                                                                key = DbVal.ConvertTo(Of String)(resAccountName)

                                                      obj = Nothing

                                                      Dim elem As IColElem = Nothing

                                                      Dim bag As New PropertyBag()

                                                      If elemsByKey.TryGetValue(key, elem) Then

                                                                '

                                                                ' Found -> Update

                                                                '

                                                                VID_Write2Log(logFile,String.Format("UPDATE: key {0}", key))

                                                                ' Element in der Collection für die Übermengenbehandlung markieren

                                                                elem.IsSelected = True

                                                                ' Map values

                                                                Dim found As Boolean = False

                                                                If DbVal.Compare(elem.GetRaw("UID_Person"), resUID_Person, ValType.String) <> 0 Then

                                                                          bag.PutValue("UID_Person", resUID_Person)

                                                                          found = True

                                                                End If

                                                                'If DbVal.Compare(elem.GetRaw("UID_UNSContainerB"), resUID_UNSContainerB, ValType.String) <> 0 Then

                                                                '          bag.PutValue("UID_UNSContainerB", resUID_UNSContainerB)

                                                                '          found = True

                                                                'End If

                                                                If found Then

                                                                          ' Create Object only When values have changed

                                     

                                                                          obj = elem.Create()

                                                                          If Not obj.IsLoaded Then

                                                                                    obj.Load()

                                                                          End If

                                                                Else

                                                                          counter.Increment(LineType.Unchanged)

                                                                End If

                                                      Else

                                                                '

                                                                ' Not found -> Insert

                                                                '

                                                                VID_Write2Log(logFile,String.Format("INSERT: key {0}", key))

                                                                obj = Connection.CreateSingle("UNSAccountB")

                                                                ' Fill keys and values

                                                                bag.PutValue("AccountName", resAccountName)

                                                                bag.PutValue("UID_Person", resUID_Person)

                                                                bag.PutValue("UID_UNSContainerB", resUID_UNSContainerB)

                                                                bag.putValue("XProxyContext","DBApp1")

                                                      End If

                                                      '

                                                      ' Additional values can be put into the bag here

                                                      '

     

                                                      If Not obj Is Nothing Then

                                                                If obj.IsDeleted Then

                                                                          ' Recall deleted object

                                                                          obj.Recall()

                                                                End If

                                                                ' Change object

                                                                bag.ChangeObject(obj, True)

                                                                Dim isUpdate As Boolean = obj.IsLoaded

     

                                                                ' Save it

                                                                If obj.IsDifferent Then

                                                                          obj.Save()

                                                                          VID_Write2Log(logFile,String.Format("SAVE {0}", valAccountName))

                                                                          If isUpdate Then

                                                                                    counter.Increment(LineType.Updated)

                                                                          Else

                                                                                    counter.Increment(LineType.Inserted)

                                                                          End If

                                                                Else

                                                                          counter.Increment(LineType.Unchanged)

                                                                End If

                                                                If elem Is Nothing Then

                                                                          ' Include in our collection to avoid double imports of elements

                                                                          Dim keyInsert As String

                                                                          keyInsert = obj.GetValue("AccountName").String

                                                                          colImport.Insert(obj)

                                                                          VID_Write2Log(logFile,String.Format("INSERT {0}", valAccountName))

                                                                          Dim elemInsert As IColElem = colImport(colImport.Count - 1)

                                                                          elemsByKey(keyInsert) = elemInsert

                                                                          elemInsert.IsSelected = True

                                                                End If

                                                      End If

                                            Catch ex As Exception

                                                      dfImport.Log(MsgSeverity.Serious, #LD("Error in line {0}: {1}", counter(LineType.Total), ViException.ErrorString(ex))#)

                              doNotDelete = True

                                                      counter.Increment(LineType.Error)

                                            End Try

                                            If (counter(LineType.Total) Mod 100) = 0 Then

                                                      dfImport.SetProgressInfo(#LD("{0} lines imported, {1} ignored, {2} inserted, {3} updated, {4} errors", counter(LineType.Total), counter(LineType.Unchanged), counter(LineType.Inserted), counter(LineType.Updated), counter(LineType.Error))#)

                                            End If

                                  Next ' ForEach line

     

            Finally

                If Not logSection Is Nothing Then

                                            logSection.Dispose()

                                            logSection = Nothing

                                  End If

            End Try

                        '

            ' Superset handling

            '

            If StopProcessing Then

                                  dfImport.Log(MsgSeverity.Warning, #LD("No superset handling, because import was stopped.")#)

                        ElseIf doNotDelete Then

                                  dfImport.Log(MsgSeverity.Warning, #LD("There were errors during the parsing of input data. No elements will be deleted to prevent data loss.")#)

                        Else

                                  logSection = dfImport.LogSection(#LD("Removing entries missing in the import")#)

                                  Try

                                            Dim toDelete As New List(Of IColElem)()

                                            For Each elem As IColElem In colImport

                                                      Try

                                                                If elem.IsSelected Then

                                                                          Continue For   ' Found in the import

                                                                End If

                                                                VID_Write2Log(logFile,String.Format("Marking {0} - {1}for removal",elem.GetValue("UID_UNSAccountB").String,elem.GetValue("UID_UNSGroupB").String))

                                                                toDelete.Add(elem)

                                                      Catch ex As Exception

                                                                dfImport.Log(MsgSeverity.Serious, #LD("Error removing object {0}", elem.Display)#)

                                                                dfImport.LogExecption(ex)

                                                      End Try

                                            Next

                                            For Each elem As IColElem In toDelete

                                                      Dim display As String = Nothing          ' There are no displays in slim collections

                                                      Try

                                                                obj = elem.Create()

                                                                display = obj.Display

                                                                obj.Delete()

                                                                obj.Save()

                                                                VID_Write2Log(logFile,String.Format("Executed removal ok"))

                                                                counter.Increment(LineType.Deleted)

                                                                dfImport.SetProgressInfo(#LD("{0} of {1} deleted", counter(LineType.Deleted), toDelete.Count)#)

                                                      Catch ex As Exception

                                                                If String.IsNullOrEmpty(display) Then

                                                                          display = New DbObjectKey(table, elem).ToXmlString()

                                                                End If

                                                                dfImport.Log(MsgSeverity.Serious, #LD("Error deleting object {0}", display)#)

                                                                dfImport.LogExecption(ex)

     

                                                                counter.Increment(LineType.Error)

                                                      End Try

                                            Next

                                  Finally

                                            If Not logSection Is Nothing Then

                                                      logSection.Dispose()

                                                      logSection = Nothing

                                            End If

                                  End Try

                        End If

        Finally

           

                        Connection.Variables.Remove("FULLSYNC")

        End Try

              Using dfImport.LogSection(#LD("Resultate")#)

                        dfImport.Log(#LD("{0} lines imported", counter(LineType.Total))#)

                        dfImport.Log(#LD("{0} header lines", counter(LineType.Header))#)

                        dfImport.Log(#LD("{0} inserted", counter(LineType.Inserted))#)

                        dfImport.Log(#LD("{0} changed", counter(LineType.Updated))#)

                        dfImport.Log(#LD("{0} deleted", counter(LineType.Deleted))#)

                        dfImport.Log(#LD("{0} not changed", counter(LineType.Unchanged))#)

                        dfImport.Log(#LD("{0} not found", counter(LineType.NotFound))#)

                        dfImport.Log(#LD("{0} empty lines", counter(LineType.Empty))#)

                        dfImport.Log(#LD("{0} errors", counter(LineType.Error))#)

              End Using

    End Sub

  • Hi All,

    I have a doubt here related to same script. Please suggest .

    We are assigning the SQL query to lineprovider.statement here but where will exactly the statement get executed? Is it while getlines() as below?

    For Each line As Line In lineProvider.GetLines(counter)

    The issue here is, even the query is throwing error it is not throwing any execption or no error is returned here. How can we get to know if the query is throwing some error while executing?

  • Hi All,

    I have a doubt here related to same script. Please suggest .

    We are assigning the SQL query to lineprovider.statement here but where will exactly the statement get executed? Is it while getlines() as below?

    For Each line As Line In lineProvider.GetLines(counter)

    The issue here is, even the query is throwing error it is not throwing any execption or no error is returned here. How can we get to know if the query is throwing some error while executing?