Problem when getting an entity which has been modified in another session - nhibernate

I have a strange problem in my rich client application. Here is some background:
I use one session per view model.
My view models communicate with each others with a Mediator.
I have a management view model where I display a list of my entities. I can edit an entity, which results in the opening of a new view model, which receives the id of the entity to be edited through the mediator.
When the user clicks on the Edit button, my edit view model updates the entity with its own session, and uses the Mediator again, with the edited entity id, to ask the main view model to refresh the list of the entities.
Let's say I change a boolean property called Visible, on the entity.
When I edit the entity, I can see an UPDATE call to NHibernate, updating the entity in the database.
When I come back in the main view model, I do 2 things :
I ask from NHibernate the updated entity
I refresh the list of the entities, to display all the entities, with a custom filter. (Display all the visible entities for example.)
What's weird is that the entity I get from NH in the first instruction has still the old value of the Visible property, but in the list of my visible entities, the entity I've edited is not present...
Here is the two functions of the repository I use to respectively get the entity and get the list of all the visible entities:
public virtual TEntity Get(int id)
{
return Session.Get<TEntity>(id);
}
public IEnumerable<Player> GetAllPlayersSortedByLastName(bool visible = true)
{
return from player in Session.Linq<Player>()
where player.Visible == visible
orderby player.LastName
select player;
}
What's wrong with my code? Why doesn't the entity I get back from NH in my main view model after it has been edited doesn't have the correct values?
Thanks in advance

You keep the ISession alive during the life-time of each ViewModel?
If that is the case - the Entity is present in the MainViewModel's ISession's IdentityMap - so when you ask it to refresh - it just grabs the one in the IdentityMap.
You need to ISession.Evict(updatedEntity) and then run your query again.
This is the whole idea of the 1st level cache in the ISession (to not hit the database if it has been previously loaded.
If you do not want this behaviour and want to bypass the first level cache - you can either open a child session from the session - or run in a IStatelessSession.

Related

One Core Data Entity Per NSPersistentDocument?

What's the best way to use Core Data if each document on disk corresponds to one Entity instance?
I have a data model file with one entity, and that entity has one attribute of name text and of type Text.
I have a Document.xib that has an NSObjectController that is set to 'Entity' mode and gets the managedObjectContext from the File's Owner. I have an NSTextField that is bound to the Object Controller for the Controller Key 'selection' and the Key Path 'text.' (This is just a test so I can figure out how Core Data works, but my eventual app will also only have one Entity instance per Document)
When I create a new document the textfield says 'No Selection' and is disabled.
I imagine that if I had a Table View or some other kind of way to select from among entity instances the selection would work but I don't nor do I want to. How can I hook up the NSObjectController to only have one Entity instance and to automatically 'select' it?
The intended behaviour is that I type something into the NSTextField, hit Save, close the document, re-open the document and the string in the textfield persists.
This is probably a really basic question but I can't find any tutorials or documents that would address this seemingly simple use case.
Ok, well I haven't figured it all out but my particular issue was being caused by the fact that nothing was being created. I switched out the NSObjectController for an NSArrayController, created an outlet for it in Document.m and added this to windowControllerDidLoadNib:
if (![self.arrayController selectedObjects]) {
[self.arrayController add:#""];
};
Now it seems to just manage the one Entity object.

Right way to pass a costume class to next view

I have read a lot about the patterns of sharing data between views .
I know how to use delegates,and segues to pass data(iOS), but i want to share a more deep question.
Lets say i have some tasks app, and each new task the user create, is an instance of a class called Task, that holds all the data on that task(date,text,etc) .
Now when in viewA, that shows the tasks list in a table, a user push a button to create a new task, hence has to create an object of Task class.
Than i take the user to viewB to edit the task, and maybe later to viewC .
A few options are possible, but for each i find some inconvenience.
viewA's controller is creating the Task new object,and pass it to b, than b to c, etc.
viewB's controller is creating the Task new object,than post a delegate to A,with task
It seems that the right option is 1 , but it has some problems such as that after view controller B edit the task, viewA's controller needs to reload the table with that new task- anyway, than, option 2, posting a delegate from b, seems more simple,so b is creating a Task object, than post delegate to the table in A to save it and also to reload the table with it .
Here the data is less capsulated .
Maybe i am completely wrong ,but i really try to understand how things should be done right .
Any thought will be helpful to me.
Or you could create a data model.
Consider having a TaskManager class that manages the list of tasks, creates them, and knows which one is currently selected (or most newly created). Either your TaskManager can be a singleton or can be accessed via your app delegate. Anything that needs to be done with a Task, the TaskManager handles.
That way, you make your view controllers more independent because they don't talk to each other but read and update the current state of the data model from the object that's responsible for it.

How to link the View and the ViewModel and where to create them

I have written a phone app using an MVVM framework. It came together okay - every page (view) on the phone has its own ViewModel and code within each ViewModel went away to the dataservice and retrieved appropriate data.
So I had a page showing an Agenda of upcoming items and its ViewModel retrieved a collection of events and within the XAML I bound a Listbox to this collection.
Similarly I had another page showing a OneOff Events and again, within its VM I called the data service to get a collection of data back and that was bound to a listbox within its view.
Not sure how good an implementation of MVVM this is, but, I ended up moving to a different database - and it was very easy to implement another dataservice without touching anything else and it all worked great.
Ok - so now I am looking to rework this app into a Windows Store app. I now have a main page that will show a combination of data that on the phone was shown on individual pages.
Hypothetically, assume that the Agenda items and One Off Events mentioned above are now appearing on the same main page (so much more room to show stuff)
Just struggling with what this means for ViewModel(s). If the MainPage can only work with one ViewModel, do I end up with one huge ViewModel that includes all the functionality that was in multiple VM's before.
Or should the Main ViewModel have within it collections of ViewModels. From looking around this seems to be the way it could be done, but, if so where are the ViewModels created?
It seems quite a fundamental shift from what I have done previously.
Yes, you can set different ViewModels as the binding context for different parts of your page. You can use the Locator pattern (one locator object with ViewModel properties) or Dependency Injection to keep the construction of things manageable.
Great sample code and slides by Gill Cleeren that discuss and show how the Contoso Cookbook sample application can be set up alternatively using MVVM and a ViewModelLocator class can be found here. The talk itself is on channel 9.
From these slides:
Data binding is the glue but...
A view needs to “find” its ViewModel
ViewModel is the DataContext
Can be static or dynamic
Static: View creates ViewModel and sets it as DataContext
Dynamic: at runtime, View selects its ViewModel or vice-versa
2 options:
View-First: ViewModel gets created because View is created
ViewModel-First: ViewModel is created and View gets selected

Additional actions when NSManagedObject is deleted

I have a core data 'ShoppingList' which contains 'Item' objects. I store a display order as an attribute of each item.
I would like to update the display order of all other items in the shopping list whenever an item is deleted. The code to do this is working fine when I use it in my view controller (from where the item is deleted), but since it is really related to the business objects and not the view, it would be better placed in either ShoppingList or Item.
Ideally, I would like it incorporated into the deletion of the item. So far I have tried the following:
1) Customize the standard Core Data generated ShoppingList.RemoveItemsObject (making sure to observe KVO before.after). What's strange about this way is that the item passed is stripped of its relationships to other core data entities before it gets to my code, which I need to process display orders correctly.
2) Customize Item.didTurnIntoFault. Same applies - but even attributes of the item are gone by this stage.
One answer would be to simply define a new method on ShoppingList that does my processing and then calls the original removeItemsObject. But I would prefer to know that whenever an item is removed, from anywhere, this is taken care of. This works nicely when I customize awakeFromInsert, for example - I know that whenever an item is created certain things are setup for me. But I'm surprised there's no equivalent for deletion.
Did you try to implement prepareForDeletion? Sounds like it's exactly what you're looking for.
The doc says:
You can implement this method to perform any operations required before the object is deleted, such as custom propagation before relationships are torn down, or reconfiguration of objects using key-value observing.

Updating NSTableView when enitiy is added to core data

I have a Cocoa App that I have manually added core data to. I setup the table in Interface Builder to list the entities from the data (with NSArrayController), and this is working just fine. The problem is when I insert a new entity (via code) the table does not update until I restart the app.
What do I have to do after inserting an entity and saving the context to get the table to automatically pick up the changes?
I'll assume you mean you want to update your array controller's contents, allowing the table to update as a result.
Short answer: Send your array controller a -fetch: message.
Longer answer: Only entity instances added through an array controller automatically show up in its contents array when it gets its contents via a straight fetch request (ie, when its contents array isn't bound to anything, but rather you set an entity name and a MOC, possibly a predicate, and nothing else).