I'm using CoreData and was wondering if I could somehow extend my NSManagedObjects to do custom stuff (like deleting files belonging to this instance).
In my case I have a couple of CoreData entities and each entity may have a folder or file path stored in a property. If the entity gets deleted I want this entity to take care of deleting the referenced files on its own.
Such behavior would be particularly helpful in combination with the "Cascade" deletion rule as removing an entity removes all child entities and their files.
If there is no such mechanism I would write a Category for each entity containing a custom deletion method, including cascading behavior for entities that may have children.
What would you do, is there an elegant solution to my problem? Has this been discussed before and I just haven't found it?
Thanks a lot!
Paul
You can do additional cleanup just before an object is deleted by overriding the prepareForDeletion method in your NSManagedObject subclass.
Related
I was going through HiveMetastoreBridge code in Apache Atlas and encountered few doubts.Pardon me if these questions are very naive.
HiveMetastoreBridge code
Why are we clearing relationships in findEntity method?
What does add referred entity does exactly in the background ? To be clear in toTableEntity method we are adding ObjectId of related entites as attributes as well calling addReferredEntity method of AtlasEntity.
In registerInstance method why are we creating references from first entity to other referred entities in else if statement. When will multiple entities be created and why will the first have reference to others?
In importTable method why after creating AtlasEntity processInst we are again creating AtlasEntitiesWithExtInfo createTableProcess and adding process entity and path entity to it? Why not Table entity too?
I want to implement Repository design pattern for my project but it's not clear to use CRUD operations in repositories or not. Some resources say you shouldn't use update/save/delete methods because the repository is only for saving objects in memory and you should services for other actions.
Which one is the best way?
Thanks.
A summary of Martin Fowler’s definition of the Repository pattern:
Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects.
So if we have both add and update methods, I could claim it’s not a collection-like interface, right? I shouldn’t need to bother checking if an object’s already there when adding to a set-like collection.
There are two common approaches about add/update:
Collection-oriented repositories try to mimic an in-memory collection, so you shouldn’t need to re-add an object if it was updated and already in the collection. The repository (or layers hidden below it, such as an ORM) should handle the changes to an entity and track them. You just add an object when you first create it and then no more methods are needed after the entity is changed.
Persistence-oriented repositories are aware that an object needs to be explicitly “saved” after any changes, so you can call the entity.save() method when an object is created or modified.
(Those are my interpretations of the definitions by Vaughn Vernon in Implementing Domain-Driven Design.)
delete is fine, but perhaps remove would be a better name.
I am new to Core Data modeling, and I am having a hard time understanding how one-to-many relationships work.
I have a parent entity called Task, which can have several instances of Comment entity. I modeled it like this: on Comments, a relationship to Task called task with the Task entity a destination. On Task, a relationship called comments, with Comment as its destination, and both relationships are each others inverse.
Not defining an inverse results in either warnings or error messages. While modeling this way works, I've noticed that once I create a second comment for a given Task, the first is replaced (one-to-one relationship).
What would be the correct way to tell the Core Data Model that this relationship allows many comments in one Task?
Also, since CoreData seems to manage primary keys on its own, how would I create an NSPredicate to retrieve all comments for a given Task?
Thanks for any suggestions!
First of all you need to set the plural option in the Task entity, select it in your .xdatamodeled and select the relationship property of Task entity to comments you should be able to see this
there is a plural option be sure to check that out. You must recreate your NSManagedObject if your using generated classes and also if your using sqlite store you must delete and rebuild so it will not complain about the new schema not being the same with the old one.
To check if you have a one to many relationship your Task entity should have a property called comments which is a class type of NSSet not Comments.
If you want to retrieve all comments for a given task you need to iterate the NSSet(comments) property of that task.
I'm having trouble understanding how NHibernate knows anything about objects removed from association (and then execute cascading style like delete-orphant). I mean, at a database level if I wanted to remove an association I'd have to physically log on and remove some FK. How does this happen in NH world? Do I remap my classes, remove previously established parent/child association (relationship), NH does comparative analysis, digs that something has been changed and then takes appropriate action? In this post Ayende talks about different cascading styles and delete-orphat is described as "... In addition to that, when an object is removed from the assoication and not assoicated with another object (orphaned), also delete it ..." How does this removal happen?
NHibernate watches all the mapped collections mapped that are owned by objects in the NHibernate session. As you make changes (adding/removing) NHibernate marks them as dirty. When it is time to flush the changes it compares the elements in the dirty collections and is able to identify what items have been added and removed. Depending on the cascade options for the collection NHibernate might then persist those changes to the database.
This is why you should always declare collection properties using interfaces (IList, ISet, etc.) and never replace a collection property on an object that has been loaded using NHibernate.
Additional info requested in comments:
There is a useful discussion by Fabio Maulo (NHibernate lead developer) of collection mapping here which I would strongly recommend to read. But to try and provide a brief answer to your questions:
But how does NH know that association between objects has been removed?
Generally when working in the OO model with many associations we manage relationships at the parent. That is, a child is considered to be associated with the parent when it is in a parent's collection. E.g.
child.Parent = parent;
parent.Children.Add(child); // This is the critical bit
session.Save(parent); // to have an INSERT generated here
Similarly removing an item from a collection breaks the association (assuming correct mapping attributes have used)
child.Parent = null;
parent.Children.Remove(child); // This is critical bit
session.Save(parent); // To have DELETE or UPDATE statement generated depending on cascade settings.
This is the opposite of how things work in the relational world where we manage the relationship at the child via the foreign key on the child row.
For a more detailed understanding there is nothing like downloading the NHibernate source code, creating a simple test case and then stepping through in the debugger.
What's the reason behind the "This is why..."
There are a number of things NHibernate takes care of in managing in association collections. It does this by using its own collection classes that keep track of whether they are dirty, what state they were in when they were loaded from the db and a number of other cool things. If you replace those objects then NHibernate loses that capability. So, for instance if you want to get rid of all the items in a collection you should do:
parent.Children.Clear(); // The collection object is preserved and NHibernate knows you want them all deleted.
You should NEVER do:
parent.Children = new List<X>(); // NHibernate will not track changes to this collection.
For further reading you might also want to take a look at this.
I'm considering using Core Data for an app I'm writing. However, after reading the docs I'm unsure how to model a particular relationship. Here's the basics:
I have an Entity called "ProjectFile" that has some basic string properties. (One of those is a path to a file on disk -- call it "File X" -- that my app is going to manipulate.) However, when the app manipulates file X, it may also need to manipulate OTHER files --- fileY and fileZ.
FileY and FileZ, like fileX, will be "ProjectFile" entities. So I need a way to tell Core Data "FileY and FileZ are associated with FileX." To do that, I created a relationship on the "ProjectFile" entity called "linkedFiles" and set the destination to "ProjectFile" and the inverse to "linkedFiles". I then set this as a "to-many" relationship, as each "ProjectFile" may have multiple linked files.
This seems recursive to me and I'm not sure I've done it correctly. The "linked" files (fileY and fileZ) need to exist on their own, just as fileX does. I need to be able to "delete" them from the "linkedFiles" relationship but still have them exist separately, if that makes sense. Essentially, I just need a weak relationship between separate objects in my model.
Have I done this correctly, or am I missing something? Thanks!
So, you have a data model that looks something like this:
ProjectFile{
path:string
infile<<-->>ProjectFile.infile
}
This will work because (1) Core Data relationships have directionality/cardinality and (2) each object is unique. Where you can get into trouble is with delete rules. You pretty much have to use No Action or Nullify in this circumstance or risk setting off a cascade delete. That in turn runs the risk creating orphaned objects that have no relationships and are hard to find and remove in the object graph.
A better model would encode more information in the relationships themselves. It appears that the real-world file objects you are modeling have two separate relationships to other file objects: (1) Each instance has other instances that it manipulates and (2) each instance has other instances that manipulate it. So, your model should reflect that:
ProjectFile{
path:string
toManipulateFiles<<-(nullify)->>ProjectFile.manipulatedByFiles
manipulatedByFiles<<-(nullify)->>ProjectFile.toManipulateFiles
}
This makes explicit the type relationship between the objects and lets you quickly and easily get the right objects for any particular operation. You can use Nullify on one relationship without orphaning the object on the other.
Although it isn't immediately obvious, relationships aren't just lines on a graphical model, they are actual live objects that can carry a lot of information. You need to design with this in mind.