Let say I have core data and three entity inside : Department, Employee, Inventory
So every department could have more employees, and every employee could have more items that is record as inventory.
Department <--->> Employee <---->> Inventory
Now lay say, that we have method (service,...) that return new list of employee for department.(Let assume that this could happened quickly.)
The logic is that we delete all instance of Employee of specific Department, and then insert new ones.
The best way would be (for me), that I could do something like that :
let employees_local = myDepartment.employees
if let employees = employees_local {
myDepartment.removeEmployees(employees)
}
But this (in my understanding) only remove relationship between those object and don't delete all those objects.
I know for solutions where you delete all entity of a kind (delete all Employees)
like : this post, or this one.
I even know that I can do a batch delete from ios 9 on. Like here
My question is, is there a faster/ better way to do this. Shouldn't be there a way, that you tell core data to delete all object that have no relationship on parent?
Using the example you looked at above linked as "this one".
If you use a predicate that filters the Employees by checking the relationship to Department is nil, that'd return just the data items you want. Then I suggest you could delete all of them.
Related
I implemented core data in my app with 2 Entity named "Employees" & "Departments".
They have a relationship with many to many. But no action for deletion now on relationship.
Now, I need like if any department has no employee then that department will automatically delete from DB.
Is this possible?
Thanks for your time :)
It is not possible to delete automatically if we have a trouble to fetch u need to filter the data using predicate matching with your requirements .
I am trying to understand the concept in saving and retrieving records in a one-to-many relationship entities in CoreData. i have two tables Products (Master) and Sales (Details) hence (one-to-many) relationship with the relationship key being (sales).
Issue 1: when registering a sale to a product. i create an instance of the Sales entity, populate the values, then add it to the product.sales (relationship) and attempt a managedObjectContext save.
First Question: Do i also have to enter the instance of the Sales entity into the Sales Entity? or that will be updated automatically since there is a relationship?
Second Question: If i want to query all the sales that happened to date, do i query the Sales Entity? or do i query the relationship in the Products Entity?
Thanks for your help!
tab images
First Question: Do i also have to enter the instance of the Sales entity into the Sales Entity? or that will be updated automatically since there is a relationship?
Something you might not realize here is that you are inherently saving the object by adding it to the managedObjectContext. As soon as you do something like
let sale = Sale(context: managedObjectContext)
followed by
managedObjectContext.save()
the context issues a save request to your persistent store (your actual SQL database).
Therefore your question whether you need to store the Sale as well is answered, it will always be stored upon saving the context.
Second Question: If i want to query all the sales that happened to date, do i query the Sales Entity? or do i query the relationship in the Products Entity?
That depends...
First let me give you a little tip/best practise:
Always make sure to set up an inverse relationship
In the Core Data Editor for your Product entity's relationships you can do something like this:
Your sales relationships look something like this:
A relationship is nothing more but a dependency between two entities, therefore there is always an inverse relationship between two entities, make sure you hook them up as shown above.
Why am I telling you this ? Remember I mentioned it depends what entity you do your query on ? This is where it matters.
For example, if you want the Sale for a given Product, you would query the product itself (by querying its relationship called sale):
let product = [A product instance from your Core Data store]
let sale = product.sale // returns the sale the product is associated to
If you want all the products from a given sale, you would query the Sale entity leveraging the products relationship:
let sale = [A sale from your Core Data store]
let products = sale.products // the products contained in the sale
You mentioned that you want all the sales to a given date:
It would not make any sense querying the Product entity for that because each product only has a relationship to the sale it is contained in.
So, to answer your question, you should query the Sale entity to retrieve all the sales to a given date.
I hope that helps, let me know if something is unclear.
let manageObjectContext = appDelegateObj.managedObjectContext
let entity = NSEntityDescription.entityForName("", inManagedObjectContext:manageObjectContext)
let manageObj = NSManagedObject(entity: entity!,insertIntoManagedObjectContext: manageObjectContext)
manageObj.setValue("Mark Developer", forKey: "AttributeName")
do {
try manageObjectContext.save()
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
}
I will need to look into this a bit further, as I too am still getting my head around Core Data, but until I can find the time to do that I think what might work for you is this:
issue 1: to also enter the sale into the sales entity. I do not believe this will be done for you. Where relationships really become important is in deleting. You can specify what you want he delete rules to be, whether nullify, deny, cascade, or no action. Raywenderlich.com has an excellent tutorial series on Core Data that may help you.
issue 2: I think it depends on in which table (although in CoreData the term is ManagedObject) the data you are looking for is stored. It would make most sense to me to query the sales entity. You don't have to query the whole sales entity if you do not want to. You can specify search parameters.
As of swift 3 you don't have to create the properties of a class of an entity that you created in Core Data because Core Data does that for you. You do have to initialize those properties though. Same thing is true for relationships. For example in the case of the product Class (the parent) the relationship to sales(the child) is already instantiated for you. So you can access and set the Entity Sale by getting the instance of the relationship in the Product Class. There might be other ways of doing that but I think using extensions is pretty cool.
extension Product {
//You would call this constructor like that: Product(sale) from any //part of your program as long as you "import CoreData"
//If its 1 Sale then s 1-1 if it's more than 1 it's 1-many
convenience init?(Sale or Sales) {
let MOC = (UIApplication.shared.delegate as! AppDelegate).managedObjectContext
self.init(context: MOC)
//case 1 when sale is 1-many
let sale = Sale(context: MOC)
//case 2 when sale is many-many(this can be an array of objects that you sent)
let sale1 = Sale(context: MOC)
let sale2 = Sale(context: MOC)
let sale3 = Sale(context: MOC)
//setting sale object
sale.property = ""
//Now is time to set the relationship with the object that you just set
//case when is 1 - many
self.sale = sale
//case when is many - many
self.sale?.adding(sale1)
self.sale?.adding(sale2)
self.sale?.adding(sale3)
}
Now your Product will be related to your sales....
I'm working on a data-collecting app and I'm having trouble gaining an understanding of how these concepts connect? Here is my scheme:
Site <----->> Station <------->> Observation Event
Site has one attribute, the name of a Site, and can containing multiple stations. Each station will have multiple observations over time. I have these set with the Event to the left as a parent event and created one-to-many relationships as diagrammed, Since each observation event will need to be tagged with site and station.
I'm assuming the parent entity is the best way to create this, or is that what a relationship would do? I expect the user would setup site/station data ahead of time and then observation data would be filled in as they were made.
In short, I just can't wrap my head around what a relationship does in core data and if a parent entity would be redundant. The core data documentation is just not clear to me on this. Any help would be vastly appreciated!!
In essence, what you're going to see when you generate your entity classes, is that in addition to the attributes of each entity you'll have an NSSet for the "to-many" relationship. You can reference any of the "records" in the to-Many relationship by the values in the set.
It seems complicated at first but then it makes total sense. So, if you want to look at the stations, you'll maybe have a "stations" set that includes a list of managed objects for each of the station entities for that site. Each station will contain a set with the managed objects for each of the related observations.
So, once you have a Site entity, you could look at all the stations for that site with something like this:
Site *site = (Site *) managedObjectForSite;
for (NSManagedObject *station in site.stations)
{
Station *stat = (Station *) station;
(do what you need to with the station record)
}
You "link" sites with stations by adding members to the stations set of a given site record, where each member is a station's managed object. You are relieved of the responsibility of "reading" station records -- once you have the members of the set which are loaded with the site, each of those is effectively a managed object for the related stations.
When the light comes on it will all be crystal clear at once. You have to work through it once then you'll pretty much know what's happening in there..
Please also see this as it may help: One-to-Many Relationship: CoreData
In Core Data, relationships have a similar function a foreign keys in a classic relational database setup.
In a database, you would "connect" the Site, Station and Event entities with a foreign key:
Site .id = Station .siteID
Station .id = Event .stationID
In core data this is not necessary. Neither of the two entities needs an extra ID attribute, instead you just define one-to-many relationships.
Site <--->> Station <---->> Event
The advantage: you can access the site from the station, or all the stations from the site with transparent and highly legible dot-notation as you would expect from an object graph. You can even conveniently get the site from an event object, etc.
Site *aStationsSite = station.site;
NSSet *aSitesStations = site.stations;
NSSet *aStationsEvents = station.events;
NSSet *sisterStations = station.site.stations;
Site *siteFromEvent = event.station.site;
I have created a database in which I have to store contacts in various categories. The issue comes when I have to create Sub categories in a Category like :-
Categories ->
Sub Categories->
Contacts
But the Categories can also have Contacts like
Categories -> Contacts
where the sub categories can also have contacts. I figured that nesting in core data would be used. How can I achieve this kind of a relationship ? How do I save the sub categories into the categories even though they are of the same entity ?
I have attached my core data entity relationship model here :-
There is no problem creating a "self" referencing relationship in CoreDate.
In other words, An entity may have a relationship of its own kind.
The only difference in your case between a Category and a SubCategory is the existence of a parent entity.
So there is no need to define a new entity for that part.
You can simply define a relationship:
Category.parent of type Category (say to-one in this case)
and a reverse relationship of:
Category.subCategories of type NSSet (to-many in this case) containing Category objects.
You can set all that up in your interface builder.
Now, since Category has a relationship with Contact so does all the "sub-categories" will have that relationship.
If you like your "sub-categories" to have additional properties, simply create a new entity an make it inherit from your Category entity (keeping the above setting I described).
and add to it the new properties.
If I delete a CoreData record from an entity, does that also delete the relationship that record had with another record in another entity?
It depends on the Delete Rule that you have enabled for the relationship. The Core Data Programming Guide documents these (extracted below). Have a look in the inspector to see which option you have set for your relationships. If you have a specific data model which you want comment on you should edit your question to be more specific.
Deny
If there is at least one object at the relationship destination, then the source object cannot be deleted. For example, if you want to remove a department, you must ensure that all the employees in that department are first transferred elsewhere (or fired!) otherwise the department cannot be deleted.
Nullify
Set the inverse relationship for objects at the destination to null. For example, if you delete a department, set the department for all the current members to null. This only makes sense if the department relationship for an employee is optional, or if you ensure that you set a new department for each of the employees before the next save operation.
Cascade
Delete the objects at the destination of the relationship.
For example, if you delete a department, fire all the employees in that department at the same time.
No Action
Do nothing to the object at the destination of the relationship. For example, if you delete a department, leave all the employees as they are, even if they still believe they belong to that department.