How to point to objects that aren't yet instantiated - core-data

I am preloading data on an app's first launch into Core Data, need to point to objects yet to be instantiated and can't figure out how to do this. I saw a similar question, though the solution isn't applicable in this situation.
Say I have 3 classes
class Person {
var nationOfBirth: Nation
...
}
class City {
var mayor: Person
...
}
class Nation {
var capitalCity: City
...
}
If i am loading an initial data set of nations, then cities, then people (or any other order) then no matter which order I load them in I will need to set instances yet to be instantiated (though I know they will be) and I'm struggling to figure out how to do this and will appreciate any help

One of this fields must be optional, because in your example you have cycle references. Also Optional field in this case must have week reference for another field to clear memory correctly in the end. Your code:
class Person {
var nationOfBirth: Nation
init(nation: Nation) {
nationOfBirth = nation
}
}
class City {
var mayor: Person
init(person: Person) {
mayor = person
}
}
class Nation {
weak var capitalCity: City?
}
//initialization
let nation = Nation()
let person = Person(nation: nation)
let city = City(person: person)
nation.capitalCity = city
In swift if you are declaring field in class without default initialisation you must initialise it in constructor(init). In your case you have 3 classes, each with one field of another class without default initialisation. So you need to initialise then in init method.
To initialise Person you need object of Nation, to initialise Nation you need object of City, to initialise City you need object of Nation, and again you need object of Person, than City, than Nation. As you you see it is infinity loop.
To solve this problem you need to break this loop. You can do it only with setting field of One class as optional (with ? in the end of type). After that you don't need to initialise that field in initialiser, because now it can contain nil(nothing).
If you don't need to initialise it in initialiser, you can now create member of class with optional field without object of another class and just set it in the end. In my code you can see, that City field in Nation is set as optional, so i can create member of Nation without initial City value(let nation = Nation()).
After that, as i have member of class Nation, i can create Person with initialiser that takes Nation object(let person = Person(nation: nation)).
In the same way as now we have created member of person we can create member of city(let city = City(person: person)).
In the end we have member of city, so we can set it to nation object, that was created at the beginning without city(nation.capitalCity = city).
About why we need weak reference in this case you can read hear - https://developer.apple.com/library/ios/documentation/swift/conceptual/swift_programming_language/AutomaticReferenceCounting.html#//apple_ref/doc/uid/TP40014097-CH20-XID_92

Related

CoreData with Relationships - how to avoid duplicate updates

I have CoreData with simple relationships as you can see below. One entity Word with 4 attributes and a Chapter entity with a one to many relationship (each word figures in only one chapter and chapters contains several words). When I try to import a file with a list of words and associated chapter, the chapters which are not yet in the database are created (which is what I want) but the chapters that already exists are created a 2nd time (new same entry in coredata). Is there an option I can activate in xcdatamodel to check and avoid duplicate entries on the relation entity?
Code details ->
fileprivate func saveAllWords(_ items: [(name: String, definition: String, example: String, chapter: String)]?) {
for item in items! {
let newWord = Word(context: self.context)
newWord.name = item.name.trimmingCharacters(in: .whitespaces)
newWord.definition = item.definition.trimmingCharacters(in: .whitespaces)
newWord.example = item.example.trimmingCharacters(in: .whitespaces)
newWord.option = 10 // option tag indicating that it's a new entry from external fileI generate a classic word
//
let myNewChapter = Chapter(context: self.context)
myNewChapter.name = item.chapter
newWord.chapter = myNewChapter
}
……
// Save the data in Core Data
do {
try self.context.save()
}
catch {
}
Any recommendation how to implement this uniqueness constraint to solve my duplicate issue?
You have to create a constraint for the unique attribute. It looks like you want the name of the Chapter to be unique
In your xcdatamodeld select your attribute, then right constraint and add they attribute.
Last but not least you will have to add merge policy for your Context, mostly likely in your AppDelegate. There are different merge policy. You should check them out which fits your needs most
context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy

how do I post a foreign key by some other field rather than primary key in django rest framework

I am developing a pet management api and this is what I post to the body when assigning a day of the week to a pet :
{
"day": "Sunday",
"pet_name": 2 <-- how to add pet name (rather than the primary key)(this is a foreign key)
}
How do I pass in the pet name which is the foreign key's field rather than the primary key field.
To avoid confusion I would rename the pet_name property of Day to just pet as it is referencing the Pet model.
class Day(models.Model):
pet = models.ForeignKey(Pet, on_delete=models.CASCADE, null=True)
In your DaySerializer you can then just use SlugRelatedField to be able to use the pet's name to reference the pet.
class DaySerializer(serializers.ModelSerializer):
pet_props = PropsSerializer(read_only=True, many=True)
pet = serializers.SlugRelatedField(slug_field='name')
class Meta:
model = models.Day
fields = ("id", "day", "pet", "pet_props")
The representation of this serializer will put the pet's name as value for the pet field. Also when writing, this allows you to use the pet's name to reference the pet instance which solves the actual issue in your question.
(You can technically also do pet_name = serializers.SlugRelatedField(slug_field='name'), but I would not do that to avoid confusion.)
I would recommend putting a unique constraint on your pet's name property though.
If you just want to display some readonly data, you can use SerializerMethodField:
from django.core.exceptions import ObjectDoesNotExist
class DaySerializer(serializers.ModelSerializer):
pet_name = serializers.SerializerMethodField()
def get_pet_name(self, obj):
try:
return obj.pet_name.name
except ObjectDoesNotExist:
# the day object doesn't have any
# pet associated, so return None
return None
Note: It would be better if you change the pet_name foreignkey to pet since it's holding a Pet instance, and not just its name.

Am I designing and constructing my value objects correctly?

Sorry in advance if this question is unclear. Please tell me what to change to make it a better question.
I am currently maintaining a C# WinForm system where I'm trying to learn and use DDD and CQRS principles. Vaughn Vernon's Implementing Domain Driven Design is my main DDD reference literature.
The system currently uses legacy code which makes use of Data Aware Controls.
In the Asset Inventory Context, i have designed my aggregate root Asset which composes of multiple valueObjects which are standard entries in the system:
In this Context, i'm trying to implement a use case where the user can manually register an Asset to the system.
My current implementation is the following:
From Presentation Layer:
Upon loading the RegisterAssetForm.cs it loads the existing standard entry lists of Group, ItemName, etc. through the Data Aware controls, all consisting of data rows with columnsid: int and name: string.
When the user selects the desired ItemName, Group, PropertyLevel, Department, and Category, then clicks save, a command is performed:
RegisterAssetForm.cs
...
AssetInventoryApplicationService _assetInventoryServ;
...
void btnSave_Click(object sender, EventArgs e)
{
int itemNameId = srcItemName.Value // srcItemName is a custom control whose Value = datarow["id"]
int groupId = srcGroup.Value;
string categoryId = srcCategory.Value;
string departmentId = srcDepartment.Value;
string propLvlId = srcPropLevel.Value;
...
RegisterAssetCommand cmd = new RegisterAssetCommand(itemNameId, groupId, categoryId, departmentId, propLvlId);
_assetInventoryServ.RegisterAsset(cmd);
...
}
From Application Layer:
The AssetInventoryApplicationService depends on domain services.
AssetInventoryApplicationService.cs
...
IAssetRepository _assetRepo;
...
public void RegisterAsset(RegisterAssetCommand cmd)
{
...
AssetFactory factory = new AssetFactory();
AssetID newId = _assetRepo.NextId();
Asset asset = factory.CreateAsset(newId, cmd.ItemNameId, cmd.PropertyLevelId,
cmd.GroupId, cmd.CategoryId, cmd.DepartmentId);
_assetRepo.Save(asset);
...
}
From Domain Layer:
AssetFactory.cs //not my final implementation
...
public class AssetFactory
{
...
public Asset CreateAsset(AssetID id, int itemNameId, int propLvlId, int groupId, int categoryId, int departmentId)
{
ItemName itemName = new ItemName(itemNameId);
PropertyLevel propLvl = new PropertyLevel(propLvlNameId);
Group group = new Group(groupNameId);
Category category = new Category(categoryNameId);
Department department = new Department(departmentNameId);
return new Asset(id, itemName, propLvl, group, category, deparment);
}
...
}
Sample table of what fills my value objects
+------------+--------------+
| CategoryID | CategoryName |
+------------+--------------+
| 1 | Category1 |
| 2 | Category2 |
| 3 | Category3 |
| 4 | Category4 |
| 5 | Category5 |
+------------+--------------+
I know domain models must be persistence-ignorant that's why i intend to use surrogate identites (id field) in Layer Supertype with my valueobject to separate the persistence concern from the domain.
The main property to distinguish my value objects is their Name
From the presentation layer, i send the standard entry value as integer id corresponding to primary keys through a command to the application layer which uses domain services.
Problem
* Is it right for me to pass the standard entry's id when creating the command, or should I pass the string name?
* If id is passed, how do i construct the standard entry value object if name is needed?
* If name is passed, do i need to figure out the id from a repository?
* Or am I simply designing my standard entry value objects incorrectly?
Thanks for your help.
It looks to me that you may be confusing a Value Object and an Entity.
The essential difference is that an Entity needs an Id but a VO is a thing (rather than a specific thing). A telephone number in a CRM would likely be a VO. But it would likely be an Entity in if you are a telephone company.
I have an example of VO in this post which you may find helpful - you can get it here
To answer your 'Problems' more specifically:
If you are creating some entity then it can be advantageous to pass in the id to a command. That way you already know what the id will be.
You shouldn't be able to create an invalid value object.
Why can't you pass in the name and the ID? Again - not sure this is relevant to a Value Object
I think you have designed them incorrectly. But I can't be sure because I don't know your specific domain.
Hope this helps!

C# Inheritance access confusion

public class ABC
{
}
public class DEF : ABC
{
}
public class Class1
{
ABC abc = new DEF(); //No error
DEF def = new ABC(); //Compile time error
}
Can anyone explain to me this scenario.
and under what circumstances we might use it.
Its because as per the OOD rule you can assign child to parent but you cannot assign parent to child.
//this possible as you re assigning child to parent
ABC abc = new DEF(); //No error
//this is illegal as you are trying to assign child to parent directly
DEF def = new ABC(); //Compile time error
Reconsider your design again or if you want to convert parent object to child than you need method for that conversion directly its not possible to do it as per OOD rules.
Consider real time example relation of Customer and RetailCustomer or Corporatecustomer of bank. Where you can easily say RetailCustomer or CorporateCustomer is Customer, but you cannot say Customer is RetailCustomer or CorporateCustomer because customer can be of any type.
Same goes for relation between Parent Shape Class and Child Rectangle,Circle etc. class.
This is called as Ploymorphism .
As explained in MSDN
At run time, objects of a derived class may be treated as objects of a
base class in places such as method parameters and collections or
arrays. When this occurs, the object's declared type is no longer
identical to its run-time type.
Base classes may define and implement virtual methods, and derived
classes can override them, which means they provide their own
definition and implementation. At run-time, when client code calls the
method, the CLR looks up the run-time type of the object, and invokes
that override of the virtual method. Thus in your source code you can
call a method on a base class, and cause a derived class's version of
the method to be executed.
The answer of for this question is best explained here MSDN Polymorphism
Let's say ABC is Person, while DEF is Student (which is a subclass of Person). You can always treat a Student as a Person, so the assignment to abc (of type Person) of a Student is correct, but you cannot treat a generic Person as Student, so the assignment to def is wrong (for instance, you cannot get the student number of a person which is not a student)

Design a document database schema

I'm vainly attempting to learn how to use object databases. In database textbooks the tradition seems to be to use the example of keeping track of students, courses and classes because it is so familiar and applicable. What would this example look like as an object database? The relational database would look something like
Student
ID
Name
Address
Course
ID
Name
PassingGrade
Class
ID
CourseID
Name
StartTime
StudentClass
ID
ClassID
StudentID
Grade
Would you keep StudentClasses inside of Classes which is, in turn, inside Course and then keep Student as a top level entity?
Student
ID
Name
Address
Course
ID
Name
Classes[]
Name
StartTime
Students[]
StudentID
So you have Courses, Students and Classes, which are parts of Courses and visited by Students? I think the question answers itself if you think about it. Maybe it's clearer if you go away from the pure JSON of MongoDB and look at how you would define it in an ODM (the equivalent of an ORM in RDBs) as document based DBs don't really enforce schemas of their own (example is based on MongoEngine for Python):
class Student(Document):
name = StringField(max_length=50)
address = StringField()
class Attendance(EmbeddedDocument):
student = ReferenceField(Student)
grade = IntField(min_value=0, max_value=100)
class Class(EmbeddedDocument):
name = StringField(max_length=100)
start_time = DateTimeField()
attendance_list = ListField(EmbeddedDocumentField(Attendance))
class Course(Document):
name = StringField(max_length=100)
classes = ListField(EmbeddedDocumentField(Class))
This would give you two collections: one for Students and one for Courses. Attendance would be embedded in the Classes and the Classes would be embedded in the Courses. Something like this (pseudocode):
Student = {
name: String,
address: String
}
Course = {
name: String,
classes: {
name: String,
start_time: DateTime,
attendance_list: {
student: Student,
grade: Integer
}[]
}[]
}
You could of course put the grade info in the student object, but ultimately there really isn't much you can do to get rid of that extra class.
The whole point of an OODBMS is to allow you to design your data model as if it were just in memory. Don't think of it as a database schema problem, think of it as a data modelling problem on the assumption that you have a whole lot of VM and a finite amount of physical memory, You want to make sure that you don't have to boil an ocean of page faults (or, in fact, database I/O operations) to do the operations that are important.
In a pure OODB, your model is fine.

Resources