I am developing a method to allow the service owner to deal with conflicting and duplicate Notes documents in an XPages application. I have created a resolution for the service owner to deal with any duplicates and conflicts that occur but just found that I have a few Notes documents (they are Contracts) that are duplicates because they have the same Contract ID but they are BOTH PARENTS and not one parent and one response, so they are NOT picked up by the view formula SELECT #IsAvailable($Conflict)
Why is this? How can I create a view to find these?
If a Replication/Save document is edited, it is promoted to a main document. One option may be an agent running overnight to move such documents into a Folder or code in your save function to abort if it's not a main document.
Related
I have a notes database and recently we are having an issue across random documents. Users gets error "The linked document cannot be found in the view" when they try to open a document from a view. I am not sure how to reproduce this issue.
I tried the below options to reproduce it, but no luck:
Attaching a document link to one of the Rich text field and deleting the link's target.
Attaching a file as a link and deleting the file in the target.
I am not seeing any pattern with the documents having the issue. The documents accessed few days ago, which was not accessed for more than 2 years also becomes corrupt like this.
Other details:
The Field info tab in Document properties dialog box is empty
There is no scheduled agent running overnight affecting this documents
No change was done to the database recently
We recently migrated to Notes 11.0 from 9.0
Since we have a daily backup of the database, we restore the document from one of the restored copy in which it was working fine.
A guess: did you try re-indexing the view? Shift-F9?
It could also be in the form, or even the view.
What if ...
you open the same document from a different view?
you remove some, many or all fields from the form, do you still see the error?
I think those documents have actually been deleted, and two things make me think that:
You say in a comment that rebuilding the view makes the documents disappear. I'd expect this only if the documents no longer exist.
I have in the past had LotusScript code doing view lookups which produced documents that I knew to be deleted, but the NotesDocument.IsDeleted property was False and the NotesDocument.Items property was Empty (i.e. no fields in the document). This is consistent with your saying the Field info tab is empty.
I'd check if any user action or code could delete documents. You say there are no scheduled agents, but maybe some user action could run code which deletes documents, or some users with the Delete privilege in the database ACL could be directly deleting documents using the Delete key on the keyboard.
Also check the database properties -> Info tab -> User Detail. This should show if there are recent deletions, but the record is probably limited to the last week or less.
In CRM 2011, notes get automatically created and attached to main record on lost focus event. Requirement is to remove this auto save functionality. Only till main form is open user should be able to edit notes. And newly added notes should only get saved once main form is saved. For example, if user add one note and closes the browser or do not save the main form, then that note should not get attached to main record, new note should get discarded.
I was thinking following solution:
create new custom entity TempNotesHolder
Create 1:N relationship with the entity where we want this functionality, for example Case entity
Make actual case's note section read only(it is requirement, user don't want to edit/delete functionality for notes once note get created)
Write plugin for create event of Case and create one Record for TempNotesHolder and associate it with case(RegardingId field in TempNotesHolder = incidentId) This will ensure one Case will always have only one associated TempNotesHolder record. There is no way in CRM 2011 to ensure One entity record will have only one record in associated entity i.e. 1:1 relationship. At least I don't know the way. Let me know if any one are aware about it.
On Case form, add one IFrame below Case's note section
on case form load event, get TempNotesHolderId associated with case using fetchXml.(There is no actual field in Case entity that refer to associated TempNotesHolder, hence need to use fetchXml. Some how we can add associated TempNotesHolderId to Case entity, and place that field on Case form, make it hidden, to avoid fetchXml)
Prepare url to display only notes of TempNotesHolder record.(/_controls/notes/notesdata.aspx?EnableInlineEdit=false&EnableInsert=true&id=&ParentEntity=
Set this url to newly added IFrame, so notes of associated TempNotesHolder get displayed in IFrame. It will also have link "Add New Note".
User can add note to TempNotesHolder which are not directly added to Case record.
Next develop plugin on pre save event of Case and check if there are any notes added to TempNoteHolder, if yes move those notes to Case record, and delete notes for TempNoteHolderId. This way notes will get saved to main record only on main form save.
To handle browser close event after adding few notes to TempNotesHolder, write plugin on Case pre Retrieve event, check if any notes present for associated TempNotesHolderId, if present then delete those notes. (As notes are present on TempNotesHolderId, that means due to some reason these notes are not moved to actual case record and we no longer need them, so delete them. This will ensure on case load, TempNotesHolder note section always be blank)
The above solution was fine till step 8. When I tried to add notes in TempNotesHolder, it gave me error, "Record with does not exists in TempNotesHolder". Then I checked that GUID, I disappointed to know CRM is taking IncidentId when I create note for TempNotesHolder. Then I tracked down the actual code for create notes to find why it is taking IncidentId instead of TempNotesHolderId. I found following code in "_static/_controls/notes/notes.htc" function name "UpdateNote"
xml="0"+CrmEncodeDecode.CrmXmlEncode(value)+""+_parentCrmFormSubmit.crmFormSubmitId.value+""+this.parentEntityType+""+CrmEncodeDecode.CrmXmlEncode(currentTitle)+""+this.userId+""
CRM is taking _parentCrmFormSubmit.crmFormSubmitId.value as objectid while creating note.
Now I stuck with this problem. Any thoughts to overcome this show stopper issue are appreciated. Also any other alternate solution to main requirement are also welcome.
Pravin Pujari (Microsoft Dynamics CRM 2011 Developer)
I would suggest simplifying the solution as follows:
Add a field to Case called new_notetext.
Create a Plugin against the Pre-Create and Pre-Update messages on the Case entity.
In the plugin, take anything entered into new_notetext and add a note to the Case entity using that text. Then clear the field new_notetext so nothing is saved with the record.
Should work just fine and is much simpler to implement.
I am doing "traditional" lotus notes programming (same since R5) and need to implement linking between 2 document types (forms) residing in different databases.
Document of type (A) in database (A) can reference several documents of type (B) in database (B).
And document (B) should also display its relationships with document (A), as document (B) can be related to different documents (A).
We have Many to Many relationship.
At the moment it is implemented on one side only (one to many):
Form of Document (A) contains embedded view of special
"link" documents residing in database A. This link documents are created by lotusScript when user selects documents from database (B). When user clicks on an item in this embedded view, it opens document (B).
Client wants to be able to edit this relationship on any side, so that if he edits it in form (A), form (B) is updated.
Form (B) is supposed to have the same kind of embedded view or a list of associated documents of type (A)
What is the best way to implement it?
Client's infrastracture is Lotus Domino 8.5.2 + Lotus Notes 8.5.2, so theoretically, composite applications approach may be an option.
The reason why I ask this question is that as far as I understand there is no good way in Notes to embed a view from another database.
The requirement is that the database should be present on workspace to be displayed in some sort of dodgy list.
It would be great to be able to specify target database for embedded view by server and replicaID, but instead we have a weird list of random workspace databases.
The main problem is that Notes wasn't designed to handle relationships like that between databases (nor anything besides parent child relationships for that matter). So the solution will have to be a creative one.
A couple of (off-the wall, potentially awful) ideas come to mind. One is to store the references in the documents themselves, and update them whenever the document is saved. That could all be done in LotusScript, and would require searching through the other database's documents to update their references.
Upside is that the performance when reading the documents would be excellent. There'd be no issues while reading Database A if Database B was unavailable. It keeps data local to each database. The downsides include the likelihood of save conflicts and the danger that references could get out of sync if documents aren't "saved" but instead are updated via agents, etc.
Another thought is to use agents to manage the links on a scheduled basis. If you don't need real-time up-to-date references, you could run an agent that scans Database B and updates the references in Database A. With this method you could choose either to update the Database A documents themselves - or - as it sounds like you've already done, create a set of link documents that show up in an embedded view. The latter eliminates the save conflict problem.
One more idea is to hide any references when you open a document in Database A, but provide a button to "show" or "update" references. When you click that button, it fires off LotusScript to search Database B and build a list on the fly. This would probably work quickly with less than 10,000 documents. That function could update the link documents you store on the same database which feed the embedded view.
Hope this helps!
What is the best way to implement it?
As you mention creating a composite application may allow you to do this, but would be restricted to windows rather then design level in the form.
eg.
[Window A] --- trigger ---> [Window B]
If you are not familiar with this system I did a tutorial which explains the basics.
http://www-10.lotus.com/ldd/compappwiki.nsf/dx/ibm-my-first-wire
Although the tutorial calls back to the same database, it is easy enough to point to a different one.
Personally I'd do it through XPages. I personally find it much easier to implement then through classic style notes design/comp apps. It will also allow you to display design elements within the same screen area.
As you've already heard, Lotus Notes has no referential integrity constraints built-in, you have to do it yourself.
I wouldn't be relying on document links as they're geared around UNID's which can change if you cut and paste the same document, thus losing the link. Try this,
1/ Create an "ID" field on each document. You can populate it by using #Unique in a computed field to generate an ID, and save that to the documents in both databases. You can create an agent to do this in lotusScript (LS), or formula. (Consider using the evaluate statement if doing in LS)
2/ Create a lookup view in each database that lists the documents by the new ID (don't forget to set the "sort order" of the ID column.
3/ Using an action button that can be configured for both databases, you can create a LS function that will open the the opposing databases view and return the ID field. (NotesUIWorkspace.pickliststrings would be the simplest way to pick the documents, otherwise you could build a dialogbox. Store the list of results in a field called "linkedID" as multi-value list.
4/ There may be more info that you want to store like document title or author, so you'll need to then get a handle to those documents using getdocumentbykey and then interrogating the fields you'll need to display information on screen.
5/ You can then also add a new field on the target documents you're referring to, call it "referrerID", which is a list of documents that reference the current document. This will maintain the two-way relationship.
The field that stores links must be a multi-valued field, otherwise it gets quite cumbersome to loop through list of linked document ID's and manage them.
This approach uses a static key so you can copy databases around without losing the relationships between documents the user has invested time in producing. You can (and probably will) lose those relationships if you rely on document universal ID's (described well in the #documentUniqueID documentation), if you cut and paste the document, or copy the database somewhere else they become new documents despite copying the same fields, and will be assigned a new universal ID, any document links for the old document will be invalid.
If the information you're displaying from the other database changes, you'll need to be able to refresh that data regularly, so consider writing a scheduled agent that can do the look up and refresh the relevant fields.
If the user intends to un-link or change the relationships between documents, then you'll need to add functions that loop through the key fields and keep the lists consistent with what the user is doing. So, like I said, Lotus Notes' flat data structure requires you manage all integrity constraints yourself.
If you want to get a little fancy you can use embedded views as they do support references from another database on the same server. Some tips about handling it in LotusScript here. And use an additional view that categorises your data by the referring ID. Embedded views are ok, as long as the view they're based on is not too big, otherwise it may affect the performance of the form that it is embedded into.
I'm wondering what strategies people are using to handle the creation and editing of an entity in a master-detail setup. (Our app is an internet-enabled desktop app.)
Here's how we currently handle this: a form is created in a popup for the entity that needs to be edited, which we give a copy of the object. When the user clicks the "Cancel" button, we close the window and ignore the object completely. When the user clicks the "OK" button, the master view is notified and receives the edited entity. It then copies the properties of the modified entity into the original entity using originalEntity.copyFrom(modifiedEntity). In case we want to create a new entity, we pass an empty entity to the popup which the user can then edit as if it was an existing entity. The master view needs to decide whether to "insert" or "update" the entities it receives into the collection it manages.
I have some questions and observations on the above workflow:
who should handle the creation of the copy of the entity? (master or detail)
we use copyFrom() to prevent having to replace entities in a collection which could cause references to break. Is there a better way to do this? (implementing copyFrom() can be tricky)
new entities receive an id of -1 (which the server tier/hibernate uses to differentiate between an insert or an update). This could potentially cause problems when looking up (cached) entities by id before they are saved. Should we use a temporary unique id for each new entity instead?
Can anyone share tips & tricks or experiences? Thanks!
Edit: I know there is no absolute wrong or right answer to this question, so I'm just looking for people to share thoughts and pros/cons on the way they handle master/details situations.
There are a number of ways you could alter this approach. Keep in mind that no solution can really be "wrong" per se. It all depends on the details of your situation. Here's one way to skin the cat.
who should handle the creation of the copy of the entity? (master or detail)
I see the master as an in-memory list representation of a subset of persisted entities. I would allow the master to handle any changes to its list. The list itself could be a custom collection. Use an ItemChanged event to fire a notification to the master that an item has been updated and needs to be persisted. Fire a NewItem event to notify the master of an insert.
we use copyFrom() to prevent having to replace entities in a collection which could cause references to break. Is there a better way to do this? (implementing copyFrom() can be tricky)
Instead of using copyFrom(), I would pass the existing reference to the details popup. If you're using an enumerable collection to store the master list, you can pass the object returned from list[index] to the details window. The reference itself will be altered so there's no need to use any kind of Replace method on the list. When OK is pressed, fire that ItemChanged event. You can even pass the index so it knows which object to update.
new entities receive an id of -1 (which the server tier/hibernate uses to differentiate between an insert or an update). This could potentially cause problems when looking up (cached) entities by id before they are saved. Should we use a temporary unique id for each new entity instead?
Are changes not immediately persisted? Use a Hibernate Session with the Unit of Work pattern to determine what's being inserted and what's being updated. There are more examples of Unit of Work out there. You might have to check out some blog posts by the .NET community if there's not much on the Java end. The concept is the same animal either way.
Hope this helps!
The CSLA library can help with this situation a lot.
However, if you want to self implement :
You have a master object, the master object contains a list of child objects.
The detail form can edit a child object directly. Since everything is reference types, the master object is automatically updated.
The issue is knowing that the master object is dirty, and therefore should be persisted to your database or whatnot.
CSLA handles this with an IsDirty() property. In the master object you would query each child object to see if it is dirty, and if so persist everything (as well as tracking if the master object itself is dirty)
You can also handle this is the INotifyPropertyChanged interface.
As for some of your other questions :
You want to separate your logic. The entity can handle storage of its own properties, and integrity rules for itself, but logic for how different object interact with each other should be separate. Look into patterns such as MVC or MVP.
In this case, creation of a new child object should either be in the master object, or should be in a separate business logic object that creates the child and then adds it to the parent.
For IDs, using GUIDs as the ID can save you quite a bit of problems, because then you don't have to talk to the database to determine a correct ID. You can keep a flag on the object for if it is new or not (and therefore should be inserted or updated).
Again, CSLA handles all of this for you, but does have quite a bit of overhead.
regarding undo on cancel : CSLA has n-level undo implemented, but if you are trying to do it by hand, I would either use your CopyFrom function, or refresh the object's data from the persistance layer on cancel (re-fetch).
i just implemented such a model.but not using NH, i am using my own code to persist objects in Oracle Db.
i have used the master detail concept in the same web form.
like i have master entity grid and on detail action command i open a penal just below the clicked master record row.
On Detail Add mode, i just populate an empty entity whose id were generated in negative numbers by a static field.and on Save Detail button i saved that entity in the details list of the Master Record in Asp.NET Session.
On Detail Edit,View i populated the Detail Panel with selected Detail through ajax calls using Jquery and appended that penal just below the clicked row.
On Save Button i persisted the Master Session (containing list of Details) in database.
and i worked good for me as if multiple details a master need to fill.
also if you like you can use Jquery Modal to Popup that Panel instead of appending below the row.
Hope it helps :)
Thanks,
A customer of ours has an Access 2007 application with a form for creating tasks for upload to a Sharepoint Task List. The user fills in the form (title, status, priority, start date, due date). The user then places check marks next to the sharepoint user names that this task must be assigned to (one task per sp user selected). This data is aggregeated into a TaskQueue table and the tasks are added to the Sharepoint list successfully (through a linked list - i think). The problem is that we need to include zero or more attachments for each task item. Is there a way to do this through a macro, VBA, or some other built in functionality that I haven't learned about yet?
My initial idea was to use a C# windows service that monitors this taskqueue table then uses the Lists.asmx Shareopint web service and the AddAttachment method when given the List item ID and NTFS path to the attached file to add the attachments to the task list item in Sharepoint.
After playing around with Access and setting up a linked table to a Task List in Sharepoint, I found that you can add attachments through the Access 2007 datasheet view. The problem is that you can only select one user or SP group in the Assigned TO field. They have a lot of repetitive tasks to assign to a bunch of separate people.. That's why they developed this form. If anyone has an idea on how to solve this issue please let me know. Also does anyone know of any good Access 2007/Sharepoint integration resources?
Thanks in advance!
have the attachments upload as part of the Access form.
load attachments into a Document Library
Check off users like they are currently being done
Add hyperlinks to the attachments uploaded in step 2 to the Description (rich text) field. (maybe done automatically in steps 1-2)
Leave TaskQueue table alone.
This way, 0..n documents can be included. The task list just stores structured data, and the documents are stored in a document library once, and you don't have runaway growth when attaching 1 document to 5 different tasks (resulting in 5 copies of the document).