Странности лотуса...

Тема в разделе "Lotus - Программирование", создана пользователем fedotxxl, 30 окт 2008.

  1. fedotxxl

    fedotxxl Well-Known Member

    Регистрация:
    9 ноя 2005
    Сообщения:
    614
    Симпатии:
    0
    Вот такой код
    Код (Text):
       
    Public docReq As NotesDocument


    .....


    Set agent = awfec.db.GetAgent(AgentName)
    Call awfec.docReq.Save(True, True)

    Call agent.RunOnServer(awfec.docReq.NoteID)

    Dim ViewUNID As NotesView
    Set ViewUNID = awfec.db.GetView("(AWF_CustomID)")

    Set awfec.docReq = ViewUNID.GetDocumentByKey(awfec.docReq.AWF_CustomID(0))
    В последней строке однажды произошла ошибка Type Mismatch. Как такое может быть? Я понимаю, если object variable not set....
     
  2. Medevic

    Medevic Что это ? :)
    Lotus team

    Регистрация:
    10 дек 2004
    Сообщения:
    3.346
    Симпатии:
    2
    А что странного? Число или дата в поле AWF_CustomID даст, наверное, такую ошибку. :)
    Извиняюсь, сглючил. Думал там GetDocumenByID. ;)
     
  3. D!m@n

    D!m@n Гость

    1. Что такое awfec?
    2. awfec.docReq.AWF_CustomID(0) - точно строка?
    3. awfec.docReq - точно или NotesDocument, или Variant?
     
  4. sanch

    sanch Well-Known Member

    Регистрация:
    17 июл 2006
    Сообщения:
    216
    Симпатии:
    0
    попробуй так Set awfec.docReq = ViewUNID.GetDocumentByKey(cstr(awfec.docReq.AWF_CustomID(0)),True)
     
  5. SkinGreek

    SkinGreek Гость

    сегодня столкнулся с подобной ошибкой, правда она была устойчивой...
    суть была следующая...
    есть функция
    Код (Text):
    DDGetReferencedDoc(DDocID As String, DDLIBRARY As Variant) As Notesdocument
    Она написана разработчиками Dom.Doc'a
    мой агент ее юзал следующим образом

    Код (Text):
        Set DDdoc = dstBinder.Documents.Add
    ...
    DDdoc.save
    Call DDdoc.SetToWorkingCopy
    Dim DDProfileDoc As NotesDocument  
    Set DDProfileDoc = DDGetReferencedDoc(DDdoc.Id, library)
    ...
    код падал с ошибкой Type Mismatch, на следующей строке внутри функции
    Код (Text):
    Set ReferencedDDoc = DDLIBRARY.GetDocumentByID (DDocID)
    при этом в документации написано было что DDdoc.Id возвращает String
    если этот же код вызывать в агенте то все было ок, если передавать необходимые для этого параметры функии - выдавал ошибку.
    помок совет sanch
    Код (Text):
    Set DDProfileDoc = DDGetReferencedDoc(cstr(DDdoc.Id), library)
    Но, ИМХО, это чушь какая-то до сих пор не смог понять "полу типизации" LS'a:((
     
  6. SkinGreek

    SkinGreek Гость

    сегодня лотус меня одаривает своими причудами...
    вот что я делаю не так?
    Код (Text):
        Dim AAA As NotesDocument
    Set AAA = DDGetReferencedDocForDDoc(DDdoc)
    Print "BEFORE"
    If AAA Is Nothing Then
    Print "AAA Is Nothing !!!"
    End If
    Dim BBB As NotesDocument   
    Set BBB = DDGetReferencedDoc(main.DDDocumentID(0), library)
    Print "AFTER"
    If AAA Is Nothing Then
    Print "AAA Is Nothing !!!"
    End If
    выводит следующее
    Код (Text):
    BEFORE
    AFTER
    AAA Is Nothing !!!
    функция DDGetReferencedDoc использует DDGetReferencedDocForDDoc но мне кажеться это не важно.
    глобальных переменных не юзаю

    Гуру объясните неразумному плз, каким образом вот эта строка
    Код (Text):
    Set BBB = DDGetReferencedDoc(main.DDDocumentID(0), library)
    виляет на локальную переменную AAA?
     
  7. K-Fire

    K-Fire Гость

    Думаю следующий сценарий происходит:
    DDGetReferencedDocForDDoc(DDdoc) возвращает NotesDocument, а для этого внутри функции (вернее библиотеки) определяется некая переменная NotesDatabase.
    Второй вызов каким-то образом "убивает" переменную NotesDatabase, в результате становится Nothing и уже возвращенный NotesDocument.
     
  8. SkinGreek

    SkinGreek Гость

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

    Вот код обоих функций, в них нет ничего что могло бы повлечь такое поведение

    Код (Text):
    Function DDGetReferencedDoc(DDocID As String, DDLIBRARY As Variant) As Notesdocument
    On Error Goto errorhandler

    Dim ReferencedDDoc As Variant
    Set DDGetReferencedDoc = Nothing

    'Get Domino.Doc Reference using ID
    Set ReferencedDDoc = DDLIBRARY.GetDocumentByID (DDocID) 'DocumentID(0))  
    Set DDGetReferencedDoc = DDGetReferencedDocForDDoc(ReferencedDDoc)

    Exit Function

    errorhandler:
    Select Case Err
    Case 213:
    Error 21043, gWFSession.GetText("DDDocDocNA")'"The referenced Domino.doc document cannot be located"
    Case Else
    Error Err, Error$    
    End Select
    Exit Function

    End Function

    Function DDGetReferencedDocForDDoc(DDoc As Variant) As Notesdocument
    Dim docUnID As String
    Dim cabinet As Variant
    'CabinetDb is defined globally, otherwise the document referrence retrieved from this objekt will deleted this function terminates
    Dim DBReplicaID As String
    Dim binder As Variant
    Dim serverName As String

    'get DocumentUniqueID
    DocUnID = DDoc.UniversalId

    'get DatabaseReplicaID
    Set binder = DDoc.Binder  'get parent binder
    DbReplicaID = binder.DocumentDatabase ' get replica ID of database

    'get ServerName
    Set cabinet = binder.cabinet ' get parent cabinet
    ServerName = cabinet.NotesServer ' get cannonical Name of the server

    'get the referenced document
    Set cabinetDB = New Notesdatabase("","")
    Call cabinetdb.OpenByReplicaID( ServerName, DBReplicaID )
    Set DDGetReferencedDocForDDoc = cabinetdb.GetDocumentByUNID(DocUnID )
    End Function
    Я подозреваю что проблема либо в сборщике мусора LS, либо в моем разрушенном мозге.
    Стоит добавить, что я разбил одну функцию созданную разработчиками на 2, в общем то изменения не страшные просто вынес часть функционала в другую функцию, это было необходимо для более удобного использования
     
  9. Akupaka

    Akupaka А че я?.. О.о

    Регистрация:
    4 окт 2007
    Сообщения:
    3.373
    Симпатии:
    2
    Фраза из коммента ничего не наводит на ум? :rolleyes:

     
  10. SkinGreek

    SkinGreek Гость

    значит дело в моем разрушенном мозгу:rolleyes:(((
    Ну почему все так плохо, хотя конечно оправдано убийство документа при разрушении ссылки на БД.
    единственное подходящее решение вижу в создании класса с подобными функциями.

    Akupaka
    Спасибо огромное, мне б такую внимательность как у вас))
     
  11. Akupaka

    Akupaka А че я?.. О.о

    Регистрация:
    4 окт 2007
    Сообщения:
    3.373
    Симпатии:
    2
    сделай в тех функциях, если есть желание, кеширование объектов БД, например:

    Код (Text):
    Globals
    dim dbCache list as notesDatabase

    Function DDGetReferencedDocForDDoc(DDoc As Variant) As Notesdocument

    ...


    if not(cabinetDB is nothing) then
    set dbCache(cabinetDB.Server & "!!" & cabinetDB.FilePath) = cabinetDB
    end if


    'get the referenced document
    Set cabinetDB = New Notesdatabase("","")
    Call cabinetdb.OpenByReplicaID( ServerName, DBReplicaID )
    Set DDGetReferencedDocForDDoc = cabinetdb.GetDocumentByUNID(DocUnID )
    End Function
    еще через объект gWFSession можно кешить объекты, но я не помню какой синтаксис...
     
  12. SkinGreek

    SkinGreek Гость

    ага получилось, немного с другой логикой но всеж
    Спасиб за идею. А то пришлось бы копипастить чтоб уже имеющийся интерфейс не ломать.
    Сделал вот так
    Код (Text):
        If Iselement(dbCache(ServerName & "!!" & DBReplicaID)) Then
    Set cabinetDB = dbCache(ServerName & "!!" & DBReplicaID)
    Else
    Set cabinetDB = New Notesdatabase("","")
    Call cabinetdb.OpenByReplicaID( ServerName, DBReplicaID )
    Set dbCache(ServerName & "!!" & DBReplicaID) = cabinetDB
    End If
    Единственное подложечкой сосет тот факт что dbCache глобальна на уровне библиотеки. То есть зависит от времени жизни библиотеки. Если б был класс то его временью жизни было бы по-гибче управлять. Библиотека умирает после отработки агента так?
     
  13. Akupaka

    Akupaka А че я?.. О.о

    Регистрация:
    4 окт 2007
    Сообщения:
    3.373
    Симпатии:
    2
    в общем, да, когда заканчивается выполнение использующего кода...

    ну, экземпляр класса дольше не проживет... а содержимое глобальной переменной можно убить, см. erase
     
  14. SkinGreek

    SkinGreek Гость

    я наобород чем меньше она будет жить тем лучшее, то есть инстанцию класса создал внутри функции и она умрет по окончании работы функции, а если надо чтоб кеш жил на уровне агента/формы и тд то в его декларациях и объявлять переменную данного класса.

    Ну в общем то предложенный вами вариант вполне подходит так как интерфейс библиотеки менять нельзя, а копипастить в свой класс-утилиту тоже не красиво.

    Да и время жизни вполне приемлемо.
    В общем решение самый раз. еще раз спасибо!:)
     
  15. Akupaka

    Akupaka А че я?.. О.о

    Регистрация:
    4 окт 2007
    Сообщения:
    3.373
    Симпатии:
    2
    ну, вообще-то, агент подгружает инстанс библиотеки в начале выполнения, а в конце - выгружает.
    соотв. живет эта переменная лишь для текущего выполнения агента. снова уточню, что убить ее содержимое можно в любой момент оператором erase.
    в данном случае класс не представляет преимуществ, кроме удобства, возможно...
    да не за что, в общем :)
     
Загрузка...

Поделиться этой страницей