Selected CoreData record between sessions in SwiftUI - core-data

My CoreData is made up of company and employee - where 1 company can have many employees.
I allow the user to select a company and my app displays the employees - I want this company selection to be passed between sessions. Is it best to store this selection in UserDefaults, in the CoreData or some other way? What should I be storing, the UUID of the company, an entire entity, etc.? Or am I going about this all in the wrong way?
Any help or guidance would be most appreciated.

#SceneStorage("ListView.selectedItem") private var selectedItemId: String?
You use SceneStorage when you need automatic state restoration of the value. SceneStorage works very similar to State, except its initial value is restored by the system if it was previously saved, and the value is· shared with other SceneStorage variables in the same scene.
The system manages the saving and restoring of SceneStorage on your behalf. The underlying data that backs SceneStorage is not available to you, so you must access it via the SceneStorage property wrapper. The system makes no guarantees as to when and how often the data will be persisted. -Apple
Put it anywhere the user makes a selection.
NavigationLink(
destination: Text("Item at \(item.timestamp!, formatter: itemFormatter)"),
tag: item.objectID.description,
selection: $selectedItemId,
label: {Text("Item at \(item.timestamp!, formatter: itemFormatter)")})

Related

#Username when run on server

So we recently decided to change some private views in a database to normal views. However, there is #Username in the select formula and when not calculated in a private view it obviously displays the server name.
Is there any way or function to get the username of the actual user and not the server?
Greetings,
Daniel
No, that's not possible. The view gets calculated on server and #UserName won't work there. The documentation of #UserName points out:
You should not use
#UserName in a public view, doing so produces unpredictable results.
As a workaround you can add a first categorized column with user names calculated or contained by document fields and embed this view in a form or page. There you can use #UserName to show only the category of current user (have a look at this).
No. If you want a view to dispay data specific to a user, that's what private views are for.
Even if you set up a shared view to discard its index and rebuild every time, shared views are still going to be built by the Indexer running on the server, running under the server's indentity. And it would be terribly inefficient to recalculate views for each user on the fly anyhow.
One alternative is to use views categorized by name, and design your applications to use embedded views with the Show Single Category option enabled.If the scale of the application is not too terribly large, this can work well - but it will be faster for users whose names come earlier in thew view's sort order than the users whose names come toward the end, so keep that in mind when evaluating performance.

Adding data to CoreData datastore after release

I'm using core data in my app to store all the car attributes for cars used in my game. The user can select different parts (engines, wheels, etc) which are then flagged in the datastore as being selected, so some of the data in the datastore can be changed by the user.
My question is similar to this, if I want to add a new car, how do I go about this once the app has shipped without overwriting the changes made by the user? The model hasn't changed, so i guess versioning is out. I know how to add data programmatically, but what is the best way to test if the database has already been updated with the new data?
All you really need to do is new objects to your persistent store.Depending on what way you put the new data in your app,you write methods, that add new Car objects, without touching users data anf flags, just create new one, as you did when you prepopulated your database.

creating many to many relationship between documents in different lotus notes databases

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.

Best approach for implementing Insert/Edit of Core Data Entities

Let’s suppose there is an entity called PERSON in a CoreData model and a NSPanel (displayed as a Sheet) is used to ask for the information needed to create an instance of such entity. The NSPanel also has a Save and Cancel buttons.
What would be the best way to implement this?
My current approach is to create the NSPanel and add outlets to NSTextField’s corresponding to the FirstName and LastName attributes of the PERSON Entity.
For the Save button I’ve created a Save Action that “reads” the data entered by the user through the Outlets and manually create a PERSON Entity with the provided information.
For the Cancel button, I’ve created a Cancel Action that just closes the NSPanel.
Even though the whole thing works as intended, I find this approach messy. Things get even worse with the need to implement the Edit functionality since a new method is needed to read the data from the selected Entity and pass it to the NSTextField’s, and add the required logic to the Save Action to account for the update operation.
I wonder if a full CoreData/Binding approach is possible in this scenario?
The main issue with the Full CoreData/Binding approach, at least to my short experience on these frameworks, is the fact that once the user start entering the info on a new instance, is already to late Cancel operation. Right?
The setup you describe is by no means messy. Rather, it provides ample opportunity to enhance the UI experience.
Your last point, or "main issue", is not a problem at all. You can put up the NSPanel and have the user input new values, and simply dismiss them if Cancel is pressed. Only if the Save button is pressed do you insert a new object into the core data managedObjectContext and save.
Similarly, when editing you simply retrieve the data before and populate the fields. You keep a reference to the record, if Save is pressed you modify the attributes and save the managedObjectContext. If the operation is canceled you simply discard the reference.

How to handle entity creation/editing in a master-detail

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,

Resources