Core Data entity naming convention - ios

Is there a convention for naming Core Data entity? The argument I heard for not prefixing Core Data entity is because there is no chance they will be collision since they only need to be unique within a model, which is not true because the NSManagedObject subclass generated may still collide with existing Objective-C classes.
So it seems logical for me to do two things to Core Data Entity: Prefix it with my project class prefix, and suffix it with Entity. This way, I know it's a Core Data entity, and its name will never collide with any other classes.

I have actually seen both prefixing with the project class prefix and without. I have never seen a suffix being added. I prefer without the project prefix, since if you have a remote database that you are syncing up with, I would use the same entity names. And then if you ever release a public API, do you really want your project prefix all over the place? For example, Stripe's entities are Customer, Card, etc. They use the prefix in the unique identifiers, which I like. Also, if you are using the project prefix for your other classes, you do not run the risk of overwriting, like you mention in your OP.

From here https://developer.apple.com/library/archive/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html
You cannot give an accessor a name that begins with new. This in turn means that you can’t, for example, declare a property whose name begins with new unless you specify a different getter
And as far as I know also copy keyword cant be used as suffix.

Related

iOS Core Data not performing Lightweight Migration

I have a model with two entities, let's say A and B. The model is loaded from sqlite file downloaded from the internet (conforming to Core Data's sqlite format; i.e. Tables and columns beginning with 'Z').
I added a new version for my model; introducing a non-optional integer attribute with default value of zero to the entity B. For some reason, whenever I query that entity, I get nil result, and an error object of no such column ZVERSION (version is the new attribute name), even if I'm not using version in my query.
What probably can be wrong?
You can have a attributes named 'version' - it is reserved. From apple's docs:
Note that a property name cannot be the same as any no-parameter method name of NSObject or NSManagedObject. For example, you cannot give a property the name "description". There are hundreds of methods on NSObject which may conflict with property names—and this list can grow without warning from frameworks or other libraries. You should avoid very general words (like "font”, and “color”) and words or phrases which overlap with Cocoa paradigms (such as “isEditing” and “objectSpecifier”).
(source: https://developer.apple.com/reference/coredata/nspropertydescription)
'version' is a class method of NSObject used in archiving:
https://developer.apple.com/reference/objectivec/nsobject/1415151-version
Also creating an SQL file outside of core data and importing it is not supported. Apple does not publish it's sqlite format and you may not be conforming it. Perhaps Apple has some ZVERION column that you are unaware of.

Changing a global identifier of a Core Data object with Ensembles

I am reading the Ensembles documentation where global identifiers should never change in an object life time. However, I have a Tag object which only consists with a name attribute (a string). According to the Ensembles documentation as well, the tag name can be returned as the global identifier, which is actually even better than returning a UUID for obvious reasons.
My question is, since the user is allowed to rename tags in my app, should I delete the tag object from the database and re-create it, or renaming the tag object is considered safe? (renaming the tag object will cause the app to return the new tag name as the global identifier, which seems to conflict with the warning of not changing global identifier in object's entire life cycle)
Thanks.
You should not change the global id, so the tag objects should be considered immutable. You can delete them, or insert new ones, even ones also created on other devices. But don't ever change the global id.
My advice is to create a new tag object when the user renames. Depending on your model, that may mean changing relationships from one tag object to another, but that should work well.
The nice thing about global ids is that Ensembles can merge the relationship even if you create the same tag on two devices at once.

Core Data - Fetched Property with bitmasks and abstract entities

(Data models renamed to preserve anonymity. :D )
So, I have a situation where on a Thing, whose configuration is defined by its own special object, though that object can be one of 2 class types.
I would like to be able to do Fetch Requests on this model by asking if the Thing's Configuration is of a certain known subclass, and if so, does it have a few specific flags set in its bitmask. If this is true, I define this as being "not special". Therefore, if it also has the other type of subclass as it's Configuration, it is also "not special".
My questions are these:
Have I got my syntax right? (In my app I get faults)
Why does it want to return an NSArray? (I thought its traversing a to-one relationship on a single object. How would I therefore interpret this NSArray?)
I should add that I only know Core Data via MagicalRecord more or less. And I use mogenerator too.

How many DbContext subclasses should I have, in relation to my models?

I'm learning ASP.NET MVC and I'm having some questions that the tutorials I've read until now haven't explored in a way that covers me. I've tried searching, but I didn't see any questions asking this. Still, please forgive me if I have missed an existing ones.
If I have a single ASP.NET MVC application that has a number of models (some of which related and some unrelated with each other), how many DbContext subclasses should I create, if I want to use one connection string and one database globally for my application?
One context for every model?
One context for every group of related models?
One context for all the models?
If the answer is one of the first two, then is there anything I should have in mind to make sure that only one database is created for the whole application? I ask because, when debugging locally in Visual Studio, it looks to me like it's creating as many databases as there are contexts. That's why I find myself using the third option, but I'd like to know if it's a correct practice or if I'm making some kind of mistake that will come back and bite me later.
#jrummell is only partially correct. Entity Framework will create one database per DbContext type, if you leave it to its own devices. Using the concept of "bounded contexts" that #NeilThompson mentioned from Julie Lerhman, all you're doing is essentially telling each context to actually use the same database. Julie's method uses a generic pattern so that each DbContext that implements it ends up on the same database, but you could do it manually for each one, which would look like:
public class MyContext : DbContext
{
public MyContext()
: base("name=DatabaseConnectionStringNameHere")
{
Database.SetInitializer(null);
}
}
In other words, Julie's method just sets up a base class that each of your contexts can inherit from that handles this piece automatically.
This does two things: 1) it tells your context to use a specific database (i.e., the same as every other context) and 2) it tells your context to disable database initialization. This last part is important because these contexts are now essentially treated as database-first. In other words, you now have no context that can actually cause a database to be created, or to signal that a migration needs to occur. As a result, you actually need another "master" context that will have every single entity in your application in it. You don't have to use this context for anything other than creating migrations and updating your database, though. For your code, you can use your more specialized contexts.
The other thing to keep in mind with specialized contexts is that each instantiation of each context represents a unique state even if they share entities. For example, a Cat entity from one context is not the same thing as a Cat entity from a second context, even if they share the same primary key. You will get an error if you retrieved the Cat from the first context, updated it, and then tried save it via the second context. That example is a bit contrived since you're not likely to have the same entity explicitly in two different contexts, but when you get into foreign key relationships and such it's far more common to run into this problem. Even if you don't explicitly declare a DbSet for a related entity, it an entity in the context depends on it, EF will implicitly create a DbSet for it. All this is to say that if you use specialized contexts, you need to ensure that they are truly specialized and that there is zero crossover at any level of related items.
I use what Julie Lerman calls the Bounded Context
The SystemUsers code might have nothing to do with Products - so I might have a System DbContext and a Shop DbContext (for example).
Life is easier with a single context in a small app, but for larger application it helps to break the contexts up.
Typically, you should have one DbContext per database. But if you have separate, unrelated groups of models, it would make sense to have separate DbContext implementations.
it looks to me like it's creating as many databases as there are
contexts.
That's correct, Entity Framework will create one database per DbContext type.

Using repository pattern in ASP.NET MVC with a SQL Server DB; how to mock repository so its unit testable without breaking OOD

I've been learning the ASP.NET MVC framework using the Apress book "Pro ASP.NET MVC Framework" by Steven Sanderson. To that end I have been trying out a few things on a project that I am not that familar with but are things that I thing I should be doing, namely:
Using repository pattern to access my database and populate my domain/business objects.
Use an interface for the repository so it can be mocked in a test project.
Use inversion of control to create my controllers
I have an MVC web app, domain library, test library.
In my database my domain items have an Id represented as an int identity column. In my domain classes the setter is internal so only the repository can set it.
So my quandries/problems are:
Effectively all classes in the domain library can set the Id property, not good for OOP as they should be read-only.
In my test library I create a fake repository. However since it's a different assembly I can't set the Id properties on classes.
What do others do when using a database data store? I imagine that many use an integer Id as unique identifier in the database and would then need to set it the object but not by anything else.
Can't you set your objects' IDs during construction and make them read-only, rather than setting IDs through a setter method?
Or do you need to set the ID at other times. If that's the case, could you explain why?
EDIT:
Would it be possible to divorce the ID and the domain object? Does anything other than the repository need to know the ID?
Remove the ID field from your domain object, and have your repository implementations track object IDs using a private Dictionary. That way anyone can create instances of your domain objects, but they can't do silly things with the IDs.
That way, the IDs of the domain objects are whatever the repository implementation decides they are - they could be ints from a database, urls, or file names.
If someone creates a new domain object outside of the repository and say, tried to save it to your repository, you can look up the ID of the object and save it as appropriate. If the ID isn't there, you can either throw an exception to say you need to create the object using a repository method, or create a new ID for it.
Is there anything that would stop you from using this pattern?
you can use the InternalsVisibleTo attribute. It will allow the types from an assembly to be visible from the tests (provided they are in different assemblies).
Otherwise you can leave the property read-only for the external objects but in the same time have a constructor which has an ID parameter and sets the ID property. Then you can call that constructor.
Hope this helps.

Resources