I have a data model for Formula 1 races with 3 entities:
RacingActor: Abstract entity
Pilot: inherits from RacingActor
Team: inherits from RacingActor
If I generate NSManagedObject subclasses to represent these entities, the code generated doesn't represent at all this design:
Everything inherits from NSManagedObject
Nothing prevents me from instantiating RacingActor
The team property in Pilot is of type NSManagedObject instead of Team
Is this the expected behaviour? Am I supposed to fix the code generated by Xcode? Am I missing something?
BTW, I'm using Xcode 4.3.3
Core Data at the core is an object relational mapping library. Long time ago it was called Entreprise Object Framework, part of WebObjects.
So yes, the base object for any persistant object managed by Core Data is NSManagedObject, and you can do whatever you want with them.
In your example, Team and Pilot will share a common table, and you'll be able to use queries to retrieve Teams and Pilots at once. That's the idea.
The Objective-C inheritance tree (if you use custom classes) can mirror the model you defined, but it doesn't need to. You can create a custom RacingActor class, use it as a base class for custom Team and Pilot classes, or you can tell the model to use RacingActor for Team and Pilot objects. You can even define a completely unrelated base class (provided NSManagedObject is a parent, directly or indirectly) for Team and / or Pilot if you want to.
You are then free to implement the specific behaviors you need in your business logic, either in controllers or in custom data classes.
Related
I just have started working with Realm for Swift. After reading the documentation, still I have a couple of question marks in mind.
My biggest one is, if there is a best practice for separation Model classes from Realm classes.
For example, in Java MVC projects we used DAO classes (Data Access Object classes) which were responsible for the communication with the database layer.
Our corresponding model classes only have either the dao object injected or we used service classes for this (like CRUD operations).
If I habe a Realm “Model” class, this seems now to be everything in one. But after having the object persisted to the database, changing attributes of the object in the UI-Layer results in
'Attempting to modify object outside of a write transaction - call
beginWriteTransaction on an RLMRealm instance first.'
Which brings me back to my initial though: Shouldn’t this be separated in Realm objects and model objects. Or is it OK to have "realm.write" processes in View-Classes then?
I did some research on this but the results are very vage on this.
How do you deal with this in your projects. Do you have some kind of best practice or guidance?
Many thanks in advance
John
Officially, (on the iOS side at least), there's no established best practice for abstracting the model class logic away from the actual Realm Object subclasses. That being said, I've definitely heard of apps in the past who do do this sort of logic in order to support multiple types of data frameworks.
If I were to do this, I would make a separate object class for each model implementing my own API on how to get/set data properties, and make the Realm object an internal member of this object. This object would then serve as the generic interface between my app's logic and how to save that data to Realm. That way, if I did want to swap out the data framework down the line, I could simply replace my own data object with a new one, but keep the API consistent.
In regards to that error message you posted, in order to ensure data integrity, you cannot modify a Realm object (UI thread or otherwise) unless it's in a write transaction. That being said, you could encapsulate that logic (i.e. open up a Realm write transaction on the current thread) pretty easily within that abstract object.
I'm not sure if the repository patter is just the most common thing i'm seeing or if it is the best practices for abstracting a layer between the database and the controller. found some good resources today explaining persistence ignorance and why it's good for unit testing. However I still feel unclear on a proper entity framework implementation.
my current project, I went about creating the model first. i can safely say my aggregate roots are:
Business
User
Event
Invoice
these roots are fairly rich with references to "look-up entities" in the model. That is to say that my model contains 20 some odd entities, a number of which are used primarily for look-up purposes. If i were to implement the repository patter,
do i need to create a POCO for each entity?
Do i ever reference the auto-generated EF classes/entites as attributes of a repository?
Do i always need to use a repository when interacting with the entity framework?
Do i need to create a POCO for each entity?
You should have a plain old CLR object for most entities in your model. You should also have a POCO for each complex type (value object in ddd). Cases where you might not want a POCO for an entity is when creating gerund types for m..n relationships. You can create POCOs for these in EF 4.1, but you don't have to.
Do i ever reference the auto-generated EF classes/entites as attributes of a repository?
The only auto-generated EF classes/entities that I know of in EF 4.1 code first are the dynamic proxies that are created at runtime to populate your navigation and collection properties. You can't and shouldn't try to reference these in any of your source code. Oh, and I think you may be confusing the term "attribute". Attributes are special classes that you can use to decorate classes and methods. Entity classes cannot be used as attributes in this sense.
Do i always need to use a repository when interacting with the entity framework? No. In fact a lot of people say you shouldn't create a repository until you find that you need one. But if you drive your development from unit tests, you will find need for a repository interface quickly.
In Entity Framework, your DataContext class is a repository, and one over which you have a lot of control with EF 4.1. I don't in any way mean to sound flippant, because this is a really good question with a lot of bad answers.
When you use EF, you're already using the repository pattern. Take advantage of that and write less code. Resist the urge to over-architect.
1) This depends on how your behavioral model (your objects) translates to your data model (your database.) There is truly no prescriptive guidance.
2) EF already does this, if by attributes you mean properties.
3) You already do. :-)
Stephen
I have a gem which implements my entire business logic, so that I can use it in different applications. Now, one of these applications requires persistence. How do I easily extend my existing Ruby models to support persistence? Should I monkey patch them?
To give you a bit of a background, my model objects are usually just built from XML or JSON files, but now I need to store them in an relational database.
Are there common patterns for this problem? Should I write new model objects that support persistence and map between my legacy objects and the new model objects or should I extend the existing ones to be representable in a database?
Any tips, hints, and links are highly welcome.
I am not sure that I fully understand your question. However, the DataMapper library can be very easily used to add persistence to an already existing object model after the fact, for two reasons:
It doesn't rely on class inheritance (like e.g. ActiveRecord does) but on mixin inheritance, and you can inherit from as many mixins you like, which means you won't have to change the inheritance tree of your object model just to add DataMapper to it.
The object-relational-mapping is declared explicitly in the model, not inferred from the data-store. This means that you can have very complex mappings between the data-store and your models, unlike the rather simple 1:1 table == class, row == object, column == attribute mapping of ActiveRecord.
Now, whether or not you will manage to keep the persistence aspect fully orthogonal, and e.g. in a separate gem, that's another question. You could indeed keep it in a separate library that just opens up all the model classes and include DataMapper::Resource and declare all the properties. This will allow you to still deploy your object model gem without persistence, but the persistence gem will obviously be rather tightly coupled to the object model gem.
I have a Core Data model where I have an entity A, which is an abstract. Entities B, C, and D inherit from entity A. There are several properties defined in entity A which are used by B, C, and D.
I would like to leverage this inheritance in my model code. In addition to properties, I am wondering if I can add methods to entity A, which are implemented in it's sub-entities.
For example:
I add a method to the interface for entity A which returns a value and takes one argument
I add implementations of this method to A, B, C, D
Then, I call executeFetchRequest: to retrieve all instances of B
I call the method on the objects retrieved, which should call the implementation of the method contained in B's implementation
I have tried this, but when calling the method, I receive:
[NSManagedObject methodName:]:
unrecognized selector sent to instance
I presume this is because the objects returned by executeFetchRequest: are proxy objects of some sort.
Is there any way to leverage inheritance using subclassed NSManagedObjects?
I would really like to be able to do this, otherwise my model code would be responsible for determining what type of NSManagedObject it's dealing with and perform special logic according to the type, which is undesirable.
Any help is appreciated, thanks in advance.
It should work. The objects returned by executeFetchRequest: are real instances of NSManagedObjects (or subclasses thereof.)
The steps to use custom classes in CoreData are as follows. Say you have entities A and B, where B inherits from A.
Then you need two custom classes as
#interface A:NSManagedObject{
}
-(void)someMethod:(NSString*)a;
#end;
#interface B:A{
}
-(void)someMethod:(NSString*)a;
#end;
Then set them in the XCode data modeler as shown:
This way, the CoreData automatically assigns the correct class to the NSManagedObject when it is fetched from the database.
If you're getting that exception, it means Core Data is not using your custom class. The key here is NSManagedObject -- that's the object Core Data created for the objects in your data store.
If you haven't already, you'll need to create a class that inherits from NSManagedObject, add your custom methods there, and then set entity A to use your custom class in the object model tool. If entities B, C, D, etc. have specific behaviors, you should subclass the class you created for entity A and assign those entities to use the subclasses too.
Essentially, you have a parallel hierarchy: one hierarchy of entities, and another of classes. You'll likely end up with entity X and class X for each entity in your object model.
After trying lots of solution calling isMemberOfClass on my NSManagedObject subclass before trying to use my custom method made the trick.
[thing isMemberOfClass:[Thing class]];
[thing customMethod]; //was getting unrecognized selector sent to instance here before
I had this same error for the same underlying reason, but it came about in a different situation and a different cure. Your suggestion helped me a lot!
Originally I had created my class implementing my entry by hand. I didn't know there was an Xcode menu for this. I think the link was never there! So it wasn't until I had added and began testing the new custom methods (not setter/getters) that I started to get the error.
My solution was to change the name of my class, have Xcode re-create the class for my entry via Editor->Create NS Mangage Object.... Then cut and paste in the old code into the new class. No difference in code!
Xcode seems to have some kind of internal link that is not apparent in the code.
I've taught myself Obj-C, and have been self-teaching Cocoa, but adding Core Data to my program has given me nothing but a huge headache, thanks to me needing extensive custom logic. Here are a couple of the questions that are driving me insane.
What if I want a Managed Object to own another Managed Object? It seems if I give it a to-many relationship, the owned object will simply be shared by various masters, but I want each Owner to have its own.
If I subclass an NSManagedObject, can I make simple calls to the Array Controller to remove or copy instances of ManagedObject, and assume those will be translated into the Core Data model?
If I want to programmatically edit the properties of a ManagedObject, can I get away with mere KVC calls to the Array Controller? What's all this talk about NSPredicate an NSFetchRequest to the NSManagedObjectContext from the NSManagedDataStoreDrivingMeCrazy? Can I make an NSFetchRequest that filters the relationships of an object currently selected in a table view?
Once I use a fetch request to get a group of objects, how do I go about querying their relations? Does that require a whole other FetchRequest, Predicate, and so forth? Isn't Core Data supposed to be easier? Am I missing something?
An entity is similar to a class--it's a blueprint for a managed object that will be instantiated later. Each managed object will have its own attributes and relationships to configure.
You can definitely insert and delete managed objects. You might have to do some code to support copying, but I am not sure.
Yes, the properties (attributes and relationships) of managed objects support KVC (and KVO and bindings).
You can access the object or set of objects simply by using the relationship name that you define in the model (no additional fetch or logic is required).