In Objectify, how do you load an entity by ID without knowing the parent key? - entity-framework

I have an entity group in objectify, typical SomeParentClass and SomeChildClass. I want to do something like this to load an instance of SomeChildClass from the datastore.
ofy().load.type(SomeChildClass.class).id(idOfSomeChildClassInstace);
This is returning nothing found. Seems that you need to know the parent of SomeChildClass to get it from the datestore. This I know works.
Key<SomeChildClass> k = Key.create(someParentClass.generateKey(), SomeChildClass.class, idOfSomeChildClassInstace);
ofy().load().key(k).now;
What if I want to load an instance of SomeChildClass without knowing the parent, by just having the id of SomeChildClass.

You cannot do that - the actual full identifier of an entity is the kind and id of each of its ancestors as well as it's own kind and id. That is why building the full key works, but using just the child entity id does not. Another way of looking at it that ids are only unique between siblings of the same parent.
The easiest way to solve your issue is to produce a key for your child entity, then get the 'web safe string' for it. This string contains all the information of the entity and all it's parents and can be used to fully reconstitute the full id.
Using objectify:
String websafeKey = Key.create(parentKey, Entity.class, id).getString();
Key<Entity> key = Key.create(websafeKey);
You can also do this with the low level api if you need to.

You need to know the whole Key to be able to get() an entity. A child key consists of: kind, ID and parent key. So you need to provide all three.

Related

Entity Framework 4.1: HOWTO know the next identifier assigned by Database automatically

I have POCO objects which their identifiers are unique and generated automatically by the database, so the problem is when you want to know for some reason which will be the next identifier that the database is going to assign to the next record you are inserting. As far as I know it is only possible after performin dbContext.SaveChanges() so I would like to know if I am right or is there a way to know the next identifier assigned by database automatically.
is there a way to know the next identifier assigned by database
automatically
Well, the next one NO. And if your code depends on it, you really need to change your design.
If you need the identifier to insert related objects, you should check some other questions because you can assign entities to eachother instead of ID's and it will be fine.
I agree with the general purport of the comments that having to know an identity value is "smelly". But on the other hand sometimes you have to live with a given design.
You can't really get the value of the next id, but you can get the value of the assigned id in time by using a TransactionScope.
using (var trans = new TransactionScope())
{
// Create new object
...
context.SaveChanges();
int id = newEntity.Id;
dependentEntity.IdString = string.Format("{0:0000000}", id);
context.SaveChanges();
trans.Complete();
}

Query to database with 'primary key' on GoogleAppEngine?

I've made a guestbook application using Google App Engine(GAE):python and the client is running on iPhone.
It has ability to write messages on the board with nickname.
The entity has 3 fileds:
nickname
date
message
And I'm about to make another feature that user can post reply(or comment) on a message.
But to do this, I think there should a 'primary key' to the guestbook entity, so I can put some information about the reply on a message.
With that three fields, I can't get just one message out of database.
I'm a newbie to database. Does database save some kind of index automatically? or is it has to be done by user?
And if it's done automatically by database itself(or not), how can I get just one entity with the key??
And I want to get some advise about how to make reply feature generally also. Thanks to read.
Every entity has a key. If you don't assign a key_name when you create the entity, part of the key is an automatically-assigned numeric ID. Properties other than long text fields are automatically indexed unless you specify otherwise.
To get an entity if you know the key, you simply do db.get(key). For the replies, you probably want to use a db.ReferenceProperty in the reply entity to point to the parent message; this will automatically create a backreference query in the message to get replies.
Each entity has a key, it contains information such as the kind of entity it is, it's namespace, parent entities, and the most importantly a unique identifier (optionally user specifiable).
You can get the key of an entity using the key method that all entities have.
message.key()
A key can be converted to and from a URL-safe string.
message_key = str(message.key())
message = Message.get(message_key)
If the key has a user-specified unique identifier (key name), you can access it like this
message.key().name()
Alternatively, if a key name was not specified, an id will be automatically assigned.
message.key().id()
To assign a key name to an entity, you must specify it when creating the entity, you are not able to add/remove or change the key name afterwards.
message = Message(key_name='someusefulstring', content='etc')
message.put()
You will then be able to fetch the message from the datastore using the key name
message = Message.get_by_key_name('someusefulstring')
Use the db.ReferenceProperty to store a reference to another entity (can be of any kind)
It's a good idea to use key name whenever possible, as fetching from the datastore is much faster using them, as it doesn't involve querying.

how to create a auto-incremented attribute in xcode managed object model

Hey, what i want to do is to make a int that will be the ID of the entity and auto increment itself whenever a new entity is added (just like a SQL identity property). Is this possible? i tried using indexed (checked on attribute) however there is no description to what indexed even does.
EDIT:
I am adding annotations to a map, when you click the pin the annotationview with a chevron shows up. Now when you click this button i would like to load an associated picture. However the only way i know how to link the picture to this button is to give the picture a unique id, and then set the button.tag to this id and then load based on the button.tag.
This kind of concept is contrary to the principles of Core Data - the idea is that you're managing sets of entities with properties, not rows in a database or other things that need to be uniqued. (If you're using the SQLite store, Core Data will create an ID for you behind the scenes, but you can't access it.)
You should probably reconsider (or at least give more details about) the problem you're trying to solve, because as it stands, Core Data will not let you autoincrement a variable.
If you absolutely must, you can manually increment on insert by having some NSNumber ID field on your entity, then every time you insert a new entity, get the existing entities sorted by that ID and limited to one result (using a NSFetchRequest with various options), grab that entity's ID, add one, and set it as the new entity's ID. It's a lot of work, though, and probably error-prone.
Edit: Based on the extra information, I'd say rather than trying to autoincrement an ID yourself, find some other guaranteed-unique property of the annotation and either use that directly or write a hash function that uses it to generate your unique ID. For example, use the latitude & longitude to build a single integer that uniquely represents that point within your system. Other than that, there's no way around having to increment the ID yourself.
I agree that this is a sticky problem - I haven't ever come across something like this in Core Data before, and I can see where autoincrementing might be useful :)
This is the simplest way, but takes some effort.
Create an "index" attribute in your Entity. Make it a String
When you create a new one, generate a GUID using CFUUIDCreate() and CFUUIDCreateString()
Assign the GUID to the "index" attribute
Voila, you now have a nearly-perfect unique ID, ready to use for caching locally and using as needed
CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault);
CFStringRef uuidStringRef = CFUUIDCreateString(kCFAllocatorDefault, uuidRef);
NSString* guidString = [NSString stringWithString:(__bridge NSString*)uuidStringRef];

Entity Framework won't SaveChanges on new entity with two-level relationship

I'm building an ASP.NET MVC site using the ADO.NET Entity Framework.
I have an entity model that includes these entities, associated by foreign keys:
Report(ID, Date, Heading, Report_Type_ID, etc.)
SubReport(ID, ReportText, etc.) - one-to-one relationship with Report.
ReportSource(ID, Name, Description) - one-to-many relationship with Sub_Report.
ReportSourceType(ID, Name, Description) - one-to-many relationship with ReportSource.
Contact (ID, Name, Address, etc.) - one-to-one relationship with Report_Source.
There is a Create.aspx page for each type of SubReport. The post event method returns a new Sub_Report entity.
Before, in my post method, I followed this process:
Set the properties for a new Report entity from the page's fields.
Set the SubReport entity's specific properties from the page's fields.
Set the SubReport entity's Report to the new Report entity created in 1.
Given an ID provided by the page, look up the ReportSource and set the Sub_Report entity's ReportSource to the found entity.
SaveChanges.
This workflow succeeded just fine for a couple of weeks. Then last week something changed and it doesn't work any more. Now instead of the save operation, I get this Exception:
UpdateException: "Entities in 'DIR2_5Entities.ReportSourceSet'
participate in the 'FK_ReportSources_ReportSourceTypes' relationship.
0 related 'ReportSourceTypes' were found. 1 'Report_Source_Types' is expected."
The debug visualizer shows the following:
The SubReport's ReportSource is set and loaded, and all of its properties are correct.
The Report_Source has a valid ReportSourceType entity attached.
In SQL Profiler the prepared SQL statement looks OK. Can anybody point me to what obvious thing I'm missing?
TIA
Notes:
The Report and SubReport are always new entities in this case.
The Report entity contains properties common to many types of reports and is used for generic queries. SubReports are specific reports with extra parameters varying by type. There is actually a different entity set for each type of SubReport, but this question applies to all of them, so I use SubReport as a simplified example.
I realise I'm late to this, but I had a similar problem and I hacked through it for about 3 hours before I came up with a solution. I'd post code, but it's at home - I can do it later if someone needs it.
Here are some things to check:
Set a breakpoint on the SaveChanges() call and examine the object context in depth. You should see a list of additions and changes to the context. When I first looked, I found that it was trying to add all my related objects rather than just point to them. In your case, the context might be trying to add a new Report_Source_Type.
Related to the previous point, but if you're retrieving the report source, make sure it is being retrieved from the database by its entity key and properly attached to the context. If not, your context might believe it to be a new item and therefore its required relationships won't be set.
From memory, I retrieved my references using the context.GetObjectByKey method, and then explicitly attached those objects to the context using the context.Attach method before assigning them to the properties of my original object.
I got this error because the table didn't have a primary key, it had a FK reference, but no PK.
After adding a PK and updating the model all is well.
Check if your ReportSource was loaded with the NoTracking option or if its EntityState == 'Detached'. If so, that is your problem, it must be loaded in the context.
This tends to happen if your database tables have a 1 - 1 relationship with each other. In your example reportsourceset expects a reportsorttypes with whatever id it is referencing. I have run into this problem when my relationship is linking two primary keys from opposite tables together.
I've got the same error because of new object instance which created "behind the scene" in "Added" state. This was not obvious.
I got this error when I added the new entity to the context but forgot to add the new entity to its parent's collection in the object graph.
For example:
Pet pet = new Pet();
context.Pets.Add(pet);
// forgot this: petOwner.Pets.Add(pet);

Can I tell Core Data to use a specific unique ID for an y object when saving it?

Example: I read data from an XML file. This data has unique id elements. I want to store those objects with their original unique id. How would I do that?
I figured out I could ask the managed object for it's ID, like this:
NSManagedObjectID *moID = [managedObject objectID];
but here the problem is: The XML tells me with the id element which object this is, and I need to look up in the database of core data if this object already exists in there, or not. So is it the only option to make an id attribute in my managed object model for that entity and then query for that? Then I will have two id systems right?
Don't worry about the ObjectID of Core Data. This is an internal unique ID which is not guarantied to be constant during the object's life cycle (e.g. it will change when you save the object to sql store). Just create a new mandatory attribute in your model and flag it as indexed so retrieval will be fast.
In the entity associated to this kind of objects, simply add another attribute of type string, call it objectID or similar and declare it to be mandatory.