Core Data - Relationship - core-data

Please let me know how to save objects through relationship.
If I have two entities like Notes , Category entity
Note is one to one for Category.
Category Many to one for Notes.
How to save , if we have Category context to Notes..
Please provide me some inputs.
How to save through sets. It would be greatful
I have Employee and Department entities. Department has one to many relationship with Employee. Employee has one to one relationship with Department. I want save object of employee entity using department entity.
Each time I have create new Object for Employee –
import UIKit
import CoreData
class ViewController: UIViewController {
var container: NSPersistentContainer? = (UIApplication.shared.delegate as? AppDelegate)?.persistentContainer
let appDelegate = UIApplication.shared.delegate as! AppDelegate
var empSet = NSSet()
var empS = Set<EmployeeExample>()
override func viewDidLoad() {
super.viewDidLoad()
var context:NSManagedObjectContext = (container?.viewContext)!
let dept = NSEntityDescription.insertNewObject(forEntityName: "Department", into: context) as! Department
let emp = NSEntityDescription.insertNewObject(forEntityName: "Employee", into: (container?.viewContext)!) as! Employee
emp.firstName = "YYYY"
emp.lastName = "HHHHHHH"
empS.insert(emp)
print("Count of Emp SSSS Set == \(empS.count)")
let emp1 = NSEntityDescription.insertNewObject(forEntityName: "Employee", into: (container?.viewContext)!) as! Employee
emp1.firstName = "RRRRR"
emp1.lastName = "YYYYY"
empS.insert(emp1)
empSet.addingObjects(from: empS)
dept.deptName = "CCC"
print("Count of Emp SSSS Set == \(empS.count)")
print("Count of Emp Set == \(empSet.count)")
dept.addToEmp(empSet)
do {
try appDelegate.saveContext()
print("Saved -------------")
}catch {
print("Error")
}
}
}

I have doubt in these lines anEmployee.department = newDepartment How to get the newDepartment value. Whether i have to declare let newDepartment = NSEntityDescription.insertNewObject(forEntityName: "Department", into: (container?.viewContext)!) as! Department.
The Department object here is whatever object should be related to that specific Employee object. How you get it depends on how your app works, but you probably want to do one of these:
If the employee belongs to a new department that doesn't already exist in your app, you create a new instance of Department and assign that object as anEmployee.department.
If the employee belongs to a department that already exists in your app, you use an already existing Department. You probably get that by fetching Department objects from Core Data-- either with NSFetchRequest or by using an NSFetchedResultsController.

Related

Swiftui CoreData one to many relationship

For example two models Person and Car. Person has many cars. My question is how to add car to already created Person. If I tray in AddNewCarView:
var person: Person
...
var newCar = Car(context: viewContext)
newCar.name = name
newCar.model = model
And now, what...?
newCar.person = person (gives newCar to all persons)
Or.
person.addToCars(newCar)
Is that something I have to add in predicate? In Car I have:
static func fetchCars() -> NSFetchRequest<Car> {
let request: NSFetchRequest<Car> = Car.fetchRequest()
reqest.predicate = NSPredicate(format: "", ) ..?
request.sortDescriptors = [NSSortDescriptor(keyPath: \Car.timestamp, ascending: true)]
return request
}

CoreData:Relationship:Save:Query

I have EmployeeExample and Deptt as entities.
EmployeeExample one to one relationship with Dept
Dept has more than one relationship with EmployeeExample
I want to save data through relationship. I have dept entity object, with that I want to save employeeexample entity
I achieved this, but I want to know whether it is the optimal way. Any optimal way? I would like to know how the relationship works.
My code :
import UIKit
import CoreData
class ViewController: UIViewController {
var container: NSPersistentContainer? = (UIApplication.shared.delegate as? AppDelegate)?.persistentContainer
let appDelegate = UIApplication.shared.delegate as! AppDelegate
var empSet = NSSet()
var empS = Set<EmployeeExample>()
override func viewDidLoad() {
super.viewDidLoad()
var context:NSManagedObjectContext = (container?.viewContext)!
let dept = NSEntityDescription.insertNewObject(forEntityName: "Deptt", into: context) as! Deptt
let emp = NSEntityDescription.insertNewObject(forEntityName: "EmployeeExample", into: (container?.viewContext)!) as! EmployeeExample
emp.firstName = "YYYY"
emp.lastName = "HHHHHHH"
empS.insert(emp)
print("Count of Emp SSSS Set == \(empS.count)")
let emp1 = NSEntityDescription.insertNewObject(forEntityName: "EmployeeExample", into: (container?.viewContext)!) as! EmployeeExample
emp1.firstName = "RRRRR"
emp1.lastName = "YYYYY"
empS.insert(emp1)
empSet.addingObjects(from: empS)
dept.deptName = "CCC"
print("Count of Emp SSSS Set == \(empS.count)")
print("Count of Emp Set == \(empSet.count)")
dept.addToEmp(empSet)
do {
try appDelegate.saveContext()
print("Saved -------------")
}catch {}
}
}
Do I have to create an Employee instance each time?
Do I have to create an Employee instance each time?
Well, do you have a new employee each time? If you have new information, you need to create a new Employee record. If you're using existing information, you look up an existing Employee from your persistent store by using NSFetchRequest. You create new instances when you have new data to save. Whether you need to do that is something only you can answer. If you have new data, yes. Otherwise, no.

Swift set or update asset in core data

Two Entities
Gymnast is one to many to Meet
I would like to when I save a new meet, it gets assigned to as a meet to each gymnast where they can then score their individuals scores for each event
Maybe I completely wrong in my logic, but here is what I am trying to do
let request = NSFetchRequest(entityName: "Gymnast")
do {
let entities = try AD.managedObjectContext.executeFetchRequest(request) as! [Gymnast]
for item in entities {
if let first = item.valueForKey("firstName"), last = item.valueForKey("lastName") {
print("Name: \(first) \(last)")
let myMeet = NSEntityDescription.insertNewObjectForEntityForName("Meet", inManagedObjectContext: AD.managedObjectContext) as! Meet
myMeet.meetName = "Winter Classic"
let myMeets = item.meets!.mutableCopy() as! NSMutableSet
myMeets.addObject(myMeet)
item.meets = myMeets.copy() as? NSSet
AD.saveContext()
}
}
} catch {
}
}
}
I think it is not ideal to replicate the Meet object over and over again for each Gymnast. For example, the meetName will be stored multiple times. I am not sure this is intended.
However, going with your setup, your problem is how you assign the to-many relationship. For a one-to-many it is always easier to simply set the to-one relationship. (Remember, there is always a reverse relationship in the Core Data model.)
Thus,
myMeet.gymnast = item
is all you need.
To add and remove to-many relationships, you can use this extension:
// Support adding to many-to-many relationships
extension NSManagedObject {
func addObject(value: NSManagedObject, forKey key: String) {
let items = self.mutableSetValueForKey(key)
items.addObject(value)
}
func removeObject(value: NSManagedObject, forKey key: String) {
let items = self.mutableSetValueForKey(key)
items.removeObject(value)
}
}

swift core data fetching relationship

I'm a little bit confused try to fetch relation data from coredata in swift
Person Entity
contains the name of person and Unique Id. The relation with Books is ONE to Many
For example
Person Entity:
idPerson = 25 - namePerson = John
idPerson = 26 - namePerson = Steve
Books Entity contains the title of books, Unique Id for the book and a relation ID with person (personBook). The relation with Person is ONE to ONE
For example
Books Entity:
idBook = 2543 - titleBook = title one - personBook = 25
idBook = 2544 - titleBook = title two - personBook = 25
idBook = 2545 - titleBook = title three - personBook = 26
here my data model screenshot: (no image because i have no reputation)
Person class
#objc(Person)
class Person: NSManagedObject {
#NSManaged var idPerson: String
#NSManaged var namePerson: String
#NSManaged var booksRel: NSSet
}
Books class
#objc(Books)
class Books: NSManagedObject {
#NSManaged var bookTitle: String
#NSManaged var idBook: String
#NSManaged var personBook: String
#NSManaged var personRel: Person
}
Fetch code
let appDel:AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
let context:NSManagedObjectContext = appDel.managedObjectContext!
let request = NSFetchRequest(entityName: "Books")
request.returnsObjectsAsFaults = false
request.fetchLimit = 30
////////////////////////////
// CODE TO JOIN Person entity WHERE personBook = idPerson
////////////////////////////
var results:NSArray = context.executeFetchRequest(request, error: nil)!
for temp in results {
var data = temp as Books
///////////////////////////////////////
//println(data.namePerson) ----> not working
///////////////////////////////////////
}
is possibile to fetch for every book the related namePerson based on namePerson = personBook ?
Thank you very much!
You don't need a property personBook for your Books entity.
Let's create a Person managedObject (using Swift 1.0):
let person = NSEntityDescription.insertNewObjectForEntityForName("Person", inManagedObjectContext: context) as Person
person.idPerson = 23
person.namePerson = "John"
var error: NSError?
if !context.save(&error) {
println("Unresolved error \(error), \(error!.userInfo)")
abort()
}
When you create a Books managedObject, you can link it to person like this:
let book = NSEntityDescription.insertNewObjectForEntityForName("Books", inManagedObjectContext: context) as Books
book.bookTitle = "My book Title"
book.idBook = 2547
book.personRel = person
var error: NSError?
if !context.save(&error) {
println("Unresolved error \(error), \(error!.userInfo)")
abort()
}
Now, when you want to make a fetch on Books, you can do like this:
let fetchRequest = NSFetchRequest(entityName: "Books")
var error: NSError?
var booksArray = context.executeFetchRequest(fetchRequest, error:&error)
if let error = error {
println("Unresolved error \(error), \(error.userInfo)")
abort()
}
for book in booksArray as [Books] {
let person = book.personRel as Person
println(person.namePerson)
println(person.idPerson)
}
If I have understood your question / data structure correctly, you will want to do something like:
let fetchRequest = NSFetchRequest(entityName: "Books")
let bookPersonPredicate = NSPredicate(format: "personRel.idPerson == %#", person.idPerson)
fetchRequest.predicate = bookPersonPredicate

Get entities by multiple ids in N:N relation

Given entities:
Team, User. Relation between those is N:N.
Question:
How do I find users which belong to specified teams (with given list of ids).
PS.
I found how to do with single team, but have no clue how to deal with the list of teams?
var team_id = ...
QueryExpression query = new QueryExpression("user");
// setting up relation between teams and users
Relationship rel = new Relationship();
rel.SchemaName = "new_teams_users";
RelationshipQueryCollection relatedEntity = new RelationshipQueryCollection();
relatedEntity.Add(rel, query);
RetrieveRequest request = new RetrieveRequest();
request.RelatedEntitiesQuery = relatedEntity;
request.ColumnSet = new ColumnSet(new string[] {"id"});
request.Target = new EntityReference { Id = team_id, LogicalName = "new_team" };
// Results: List of users by team id.
RetrieveResponse response = (RetrieveResponse)CrmService.Execute(request);
QueryExpression build on intersect entity will help you. As example i used product and competitor N:N relationship
QueryExpression qe = new QueryExpression()
{
EntityName = "competitorproduct", //this name can be get from N:N rel properties (Relationship form, Relationship Entity Name field)
ColumnSet = new ColumnSet(true),
};
qe.Criteria.AddCondition(
"competitorid",
ConditionOperator.In,
new object[] { "GUID1", "GUID2"});
//Below is optional - if you need some details of entity, add LinkEntity object. This example adds all fields from product entity
LinkEntity lePorduct = new LinkEntity("competitorproduct", "product", "productid", "productid", JoinOperator.Inner);
lePorduct.Columns = new ColumnSet(true);
qe.LinkEntities.Add(lePorduct);
You would make your primary entity the intersection entity so in your example it would be "TeamMembership" the criteria would then be set against the attribute "SystemUserId".
To get more information on the team you need to add the team entity as a linked entity to your query like this
LinkEntity TeamLink = new LinkEntity();
TeamLink .EntityAlias = "TeamLink ";
TeamLink .JoinOperator = JoinOperator.Inner;
TeamLink .LinkFromEntityName = "teammembership";
TeamLink .LinkFromAttributeName = "teamid";
TeamLink .LinkToEntityName = "team";
TeamLink .LinkToAttributeName = "teamid";
You can then bring back what ever columns you want and get the data out.

Resources