Связывание объектов Notesdocument

Тема в разделе "Lotus - Программирование", создана пользователем Kizarek86, 12 янв 2011.

  1. Kizarek86

    Kizarek86 Lotus team
    Lotus team

    Регистрация:
    20 июл 2007
    Сообщения:
    857
    Симпатии:
    5
    Собственно проблема в чем:

    Это некоторый кусок логики при самописном логировании

    Есть агент вызываемый через Ajax под Web, в нем получаем (через GetDocumentByUNID) документ (DOC1) изменяем его (пока не сохраняем), передаем этот документ в некоторую функцию в библиотеке, в которой получаем (также через GetDocumentByUNID) этот же документ (DOC2).
    Так вот как я понимаю, получается так что и в DOC1 и в DOC2 теперь хранится один и тот же документ, причем = DOC2.

    Есть ли возможность избежать этого и иметь оба объекта и DOC1 (измененный агентом) и DOC2 тот же документ но агентом не низменный?
     
  2. lmike

    lmike нет, пердело совершенство
    Команда форума Lotus team

    Регистрация:
    27 авг 2008
    Сообщения:
    6.082
    Симпатии:
    300
  3. nvyush

    nvyush Lotus team
    Lotus team

    Регистрация:
    22 апр 2009
    Сообщения:
    2.317
    Симпатии:
    0
    М.б. поможет перед открытием DOC2 выполнить DOC1.UniversalID = "какое-то значение"
     
  4. Kizarek86

    Kizarek86 Lotus team
    Lotus team

    Регистрация:
    20 июл 2007
    Сообщения:
    857
    Симпатии:
    5
    Спасибо.
    Помогло получение второго документа через представление.
    Не очень красиво конечно, но с подменой ИД мне ещё меньше нравицо)
     
  5. morpheus

    morpheus скриптописец

    Регистрация:
    7 авг 2006
    Сообщения:
    3.927
    Симпатии:
    0
    так ведь подмена ИД ведёт к созданию нового дока?!
     
  6. VladSh

    VladSh начинающий
    Lotus team

    Регистрация:
    11 дек 2009
    Сообщения:
    1.251
    Симпатии:
    2
    Через представление необязательно.
    Можно взять БД другим методом. Например, если она была получена по пути, то взять по ReplicaiD и наоборот, док, полученный из этой БД будет другим.
    И ещё способ (я чаще всего так делаю) сделать объектам NotesDatabase и NotesSession Delete, а потом взять заново, "инстансы" будут другими и док соответственно тоже будет другим.
     
  7. TIA

    TIA :-)
    Lotus team

    Регистрация:
    15 май 2009
    Сообщения:
    790
    Симпатии:
    0
    Есть неприятные побочные эффекты. Все документы, виды и пр., полученные из NotesDatabase тоже обнулятся. Более щедящий подход -- делать Delete переполучаемому документу.
     
  8. nvyush

    nvyush Lotus team
    Lotus team

    Регистрация:
    22 апр 2009
    Сообщения:
    2.317
    Симпатии:
    0
    Если не сохранять, то новый документ не создастся. Суть моего предложения — "испортить" юнид документа (разумеется, сперва сохранить оригинал в переменной или cfd-поле для последующего восстановления), чтобы открытие с диска не затирало документ. КМК, должно работать, но сам не проверял.
    Delete doc в данном случае не поможет, т.к. "убьёт" документ в памяти, а он нам ещё нужен.
     
  9. nvyush

    nvyush Lotus team
    Lotus team

    Регистрация:
    22 апр 2009
    Сообщения:
    2.317
    Симпатии:
    0
    Иллюстрация предложенного метода:
    <div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">Код агента</div></div><div class="sp-body"><div class="sp-content">
    Код (LotusScript):
    Sub Initialize
    Const fakeUnid = "00000000000000000000000000000000"

    Dim session As New NotesSession
    Dim db As NotesDatabase
    Dim doc1 As NotesDocument
    Dim doc2 As NotesDocument
    Dim unid As String

    Set db = session.CurrentDatabase
    Set doc1 = db.CreateDocument
    Call doc1.ReplaceItemValue("Field", "old value")
    Call doc1.Save(True, True)
    unid = doc1.UniversalID
    Delete doc1
    Set doc1 = db.GetDocumentByUNID(unid)
    Call doc1.ReplaceItemValue("Field", "new value")
    doc1.UniversalID = fakeUnid
    Set doc2 = db.GetDocumentByUNID(unid)
    doc1.UniversalID = unid
    Print "doc1.Field=" + doc1.GetItemValue("Field")(0) + "; doc1.unid=" + doc1.UniversalID
    Print "doc2.Field=" + doc2.GetItemValue("Field")(0) + "; doc2.unid=" + doc2.UniversalID
    Call doc2.Remove(True)
    End Sub
    Можно завернуть в функцию вида:
    Код (LotusScript):
    Function getDocOnDisk(doc As Notesdocument) As Notesdocument
    Const fakeUnid = "00000000000000000000000000000000"
    Dim unid As String
    unid = doc.UniversalID
    doc.UniversalID = fakeUnid
    Set getDocOnDisk = doc.ParentDatabase.GetDocumentByUNID(unid)
    doc.UniversalID = unid     
    End Function
    <div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">Пример использования функции</div></div><div class="sp-body"><div class="sp-content">
    Код (Text):
    Sub Initialize
    Dim session As New NotesSession
    Dim db As NotesDatabase
    Dim doc1 As NotesDocument
    Dim doc2 As NotesDocument
    Dim unid As String

    Set db = session.CurrentDatabase
    Set doc1 = db.CreateDocument
    Call doc1.ReplaceItemValue("Field", "old value")
    Call doc1.Save(True, True)
    unid = doc1.UniversalID
    Delete doc1
    Set doc1 = db.GetDocumentByUNID(unid)
    Call doc1.ReplaceItemValue("Field", "new value")
    Set doc2 = getDocOnDisk(doc1)
    Print "doc1.Field=" + doc1.GetItemValue("Field")(0) + "; doc1.unid=" + doc1.UniversalID
    Print "doc2.Field=" + doc2.GetItemValue("Field")(0) + "; doc2.unid=" + doc2.UniversalID
    Call doc2.Remove(True) 
    End Sub
    Добавлено
    Обнаружен побочный эффект — NoteID сбрасывается в 0, а он к сожалению read-only. Попытка сохранить модифицированный документ вызывает ошибку Notes error: Database already contains a document with this ID (UNID).
     
  10. VladSh

    VladSh начинающий
    Lotus team

    Регистрация:
    11 дек 2009
    Сообщения:
    1.251
    Симпатии:
    2
    Ага, то я, когда надо "чистый" объект (до всех изменений) вытянуть так делал.
    Но и не все объекты там при Delete NotesDatabase чистятся, это была фича, я даже в коде всё вручную чищу, начиная с NotesDocument'ов и поднимаясь выше.

    А сейчас так:
    Код (Text):
    %REM
    Function reloadDoc
    Description: получение нового инстанса документа
    %END REM
    Static Function reloadDoc(ND As NotesDocument) As NotesDocument
    Dim NDB As NotesDatabase

    Server$ = ND.ParentDatabase.Server
    RID$ = ND.ParentDatabase.ReplicaID
    UNID$ = ND.UniversalID

    Set NDB = New NotesDatabase("", "")
    Call NDB.OpenByReplicaID(Server$, RID$)

    Set reloadDoc = NDB.GetDocumentByUNID(UNID$)
    End Function
     
  11. nvyush

    nvyush Lotus team
    Lotus team

    Регистрация:
    22 апр 2009
    Сообщения:
    2.317
    Симпатии:
    0
    VladSh
    Можно получить неприятный побочный эффект, если потребуется в одном скрипте получить документы с диска из разных баз. Впрочем, вероятность такой необходимости невелика.
    Другим недостатком предлагаемой функции являются статичные локальные переменные (тогда уж объявить статичной только NDB).
     
  12. VladSh

    VladSh начинающий
    Lotus team

    Регистрация:
    11 дек 2009
    Сообщения:
    1.251
    Симпатии:
    2
    nvy
    По первому - траблов не встречал, хотя получаю таким образом доки именно из разных баз.
    По второму - какие статичные локальные переменные? Они грохаются при выходе из функции, статичный только возвращаемый результат, который дополнительным параметром возвращать мне неудобно.
     
  13. nvyush

    nvyush Lotus team
    Lotus team

    Регистрация:
    22 апр 2009
    Сообщения:
    2.317
    Симпатии:
    0
    Все переменные, объявленные внутри статической функции, являются статическими, т.е. их значения сохраняются между вызовами, в том числе база данных. Именно поэтому данная функция возвращает документ, а не пустоту. Попробуйте убрать Static в объявлении функции, и она начнёт возвращать Nothing. Попробуйте добавить в начало функции строку Print "UNID=" + UNID$ и вызовите функцию два раза подряд — в первом случае получите пустой unid, во втором — имеющий значение. Логичнее было бы внутри функции объявить статической только NDB (Static NDB As NotesDatabase).
    Что касается первой проблемы, то она, кмк, может возникнуть, когда в ходе исполнения одного скрипта переоткрываются документы из разных баз. В этом случае после второго вызова NDB теряет значение первой базы и, соответственно, должен теряться первый полученный документ. Опытов не ставил, но уверен, что это будет так.

    Добавлено Это действительно так, причём даже если брать второй документ из той же базы — NDB затирается и прощай первый документ. Можно добавить второй параметр типа NotesDatabase и передавать в функцию переменную, объявленную в вызывающей процедуре, в этом случае можно и от Static избавиться.
     
  14. VladSh

    VladSh начинающий
    Lotus team

    Регистрация:
    11 дек 2009
    Сообщения:
    1.251
    Симпатии:
    2
    nvy
    Всё верно, так и произошло.
    Т.е. для 2-х и более документов в пределах одной базы все эти "конструкции" на катят. Для одного дока, чтобы его взять заново, достаточно.
     
  15. lmike

    lmike нет, пердело совершенство
    Команда форума Lotus team

    Регистрация:
    27 авг 2008
    Сообщения:
    6.082
    Симпатии:
    300
    ну и в итоге, в общем случае - возвращаемся к варианту byKey :) ?!
     
  16. VladSh

    VladSh начинающий
    Lotus team

    Регистрация:
    11 дек 2009
    Сообщения:
    1.251
    Симпатии:
    2
    В общем случае, да, - byKey
    А в итоге (по условиям задачи) хватит и одинарной перезагрузки (мне, кстати этого всегда хватало), конечно лучше модифицировав, как предложил nvy :)
     
  17. TIA

    TIA :-)
    Lotus team

    Регистрация:
    15 май 2009
    Сообщения:
    790
    Симпатии:
    0
    Не, лучше функция nvy с подменой UNID
     
  18. nvyush

    nvyush Lotus team
    Lotus team

    Регистрация:
    22 апр 2009
    Сообщения:
    2.317
    Симпатии:
    0
    Если нужно сохранять doc1 — не лучше. Эксперименты показали, что подмена unid делает документ "новым", т.е. сбрасывает NoteID в "0", попытка сохранить документ под старым unid вызывает ошибку "Notes error: Database already contains a document with this ID (UNID)". Для сохранения изменений придётся либо предварительно удалять документ с диска, например, doc2.Remove(True) (и плодить окурки), либо копировать изменения в doc2 и сохранять его. В любом случае танцы с бубном. КМК, лучше использовать доработанный вариант функции от VladSh. Для себя решил взять на вооружение такой вариант:
    Код (LotusScript):
    Function getDocOnDisk(doc As NotesDocument, db As NotesDatabase) As NotesDocument
    'возвращает сохранённый на диске документ doc, db — переменная для сохранения нового экземпляра бд
    Set db = New NotesDatabase("", "")
    Call db.OpenByReplicaID(doc.ParentDatabase.Server, doc.ParentDatabase.ReplicaID)
    Set getDocOnDisk= db.GetDocumentByUNID(doc.UniversalID)
    End Function
     
Загрузка...

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