Update a model and its relations with already existing primary keys - postgresql

I have the following struct, with LinguisticMetadata being a relation:
metadataDB := &dbm.VideoMetadata{
ID: *imdbid,
ImdbID: *imdbid,
TmdbID: tmdbID,
IsSeries: input.Episode != nil,
ImdbRating: imdbRating,
Adult: extendedMetadata.Adult,
LinguisticMetadata: linguisticListDB, // LinguisticMetadata []*LinguisticMetadata `gorm:"not null"`
Subtitles: subtitlesDB, // Subtitles []*Subtitle
}
I want to create a new metadata, or update the existing one if it already exists. This is not an issue and can be achieved easily like so:
newMetadata := dbm.VideoMetadata{}
db.Where(dbm.VideoMetadata{ID: *imdbid}).Assign(metadataDB).FirstOrCreate(&newMetadata)
However, I also need to have the same behavior for its relations. The primary keys for LinguisticMetadata is the prefix of a country, eg: "en", "fr", "it"... So it is very likely that it already exists for the given metadata. Hence, if the primary keys of the relations already exist, the model should be updated (or replaced).
With the code shown above, I get the following error if the LinguisticMetadata primary key already exists:
pq: duplicate key value violates unique constraint "linguistic_metadata_pkey"
This does not make sense to me, because as stated here:
GORM will auto save associations and its reference when creating/updating a record. if association has a primary key, GORM will call Update to save it, otherwise it will be created.

Related

Given a primary key, is it possible to find all foreign keys in EF Core model?

I'm working with a rather large EF core model that has all tables and relationships defined in code that wind up attached to a context object. If I have a primary key, is there a clean/efficient way to get all the dependent columns in the model?
As an example of what I'm working with, this snippet works to find a primary key's name for a given table (the table is known by its type T which is a parameter to the function in which this code lives):
var keyName = context.Model.FindEntityType(typeof (T)).FindPrimaryKey().Properties.Select(x => x.Name).Single();
I found the answer while poking through the properties of they key object. Instead of getting the name, get the object itself, then call these two other methods to get the foreign keys that reference the primary key:
var key = context.Model.FindEntityType(typeof (T)).FindPrimaryKey().Properties.FirstOrDefault();
var foreignkeys = key.GetContainingPrimaryKey().GetReferencingForeignKeys();

Changing primary key generation with ManyToManyMapping

I am trying to find a work-around for the EclipseLink bug bugs.eclipse.org/bugs/show_bug.cgi?id=344448.
The issue is that EclipseLink chooses a primary key made of entity ID + hashmap value ID for each entry of the HashMap. I would like to modify to have the primary key of entity ID + hashmap key ID instead. This is not only an issue with the primary key constraint but also with the SQL statements generated by EclipseLink, eg delete, update, etc...
So... I saw there is a way to customise this behaviour using a Customiser and by grabbing the ManyToManyMapping of the hashmap field and modifying whatever is needed. I can't find much documentation on this so I am sort of trying out things... but so far no success.
public class ConfigureValuesFilter implements DescriptorCustomizer {
public void customize(ClassDescriptor descriptor) throws Exception {
ManyToManyMapping mapping = (ManyToManyMapping) descriptor
.getMappingForAttributeName("values");
// various attempts
}
I tried setting the primary key with mapping.setTargetRelationKeyFieldName ("value_KEY"); and the setTargetKeyFieldNames (why does it need both?) but this resulted in an array index out of bound error with the table (from the key) I want to use not available in the descriptor, see below.
Exception Description: The table [CASEVALUE] is not present in this descriptor.
Descriptor: RelationalDescriptor(testdb.EULADocument --> [DatabaseTable(EULADOCUMENT)])
Then I tried changing the delete query statement with setDeleteSQLString, but I am stuck on how to pass the parameter values
mapping.setDeleteSQLString("DELETE FROM LICENSE_EULADOCUMENT WHERE ((values_KEY = #VALUES_KEY) AND (License_ID = #LICENSE_ID))");
says it could not find the VALUES_KEY so sets it to NULL...
What is the recommended way to modify the behaviour?

Primary key update in Realm migration

I have several cases where I have to update some object models, including the property that I use as a primary key.
For example :
Merge the primary key name (e.g. Georges, Anna...), and the familyName (e.g. Johnson, Smith...) property, and use that new merged name (e.g. Georges Johnson...) as a primary key.
Make the identifier primary key from type Int to type String
But of course the documentation clearly states that :
Once an object with a primary key is added to a Realm, the primary key cannot be changed
You can always remove old objects and create new ones, but this would add a lot of complexity to re-create the relationships.
And I'm pretty sure realm may not be happy with the identifier type change either way (judging by the thrown exceptions that I encountered).
So I was wondering if there was a simpler way to do so, or if I had to do a lot of manual grunt work to achieve my very simple goals.
Katsumi from Realm here. Realm supports primary key migration.
Primary keys can be changed only during migration. So you'd like to change the existing primary key values, you can write migration block, then you can assign new values for each new objects. The values must be unique of course.
let config = Realm.Configuration(schemaVersion: 1, migrationBlock: { (migration, schemaVersion) in
migration.enumerateObjects(ofType: "Person", { (oldObject, newObject) in
newObject!["key"] = ...
})
})
You can change primary key type as well.
In that case, you also need to write a migration block and assign new values. Because the primary key property is cleared when changing the type. Also, you can merge or split existing primary key property. You can add a new property, then specify it as a primary key, then you also should write migration block and assign new unique values as well.
However, the latest version of Realm (2.8.0 and 2.8.1) made unintentional bug that doesn't allow to modify primary key even during migration. So if you're urgent, you should use the previous version (2.7.x), if you are not urgent, please wait to be fixed the bug in next release.

Perform a Realm Migration that adds primary key

Within Realm how do you perform a Migration that adds the Primary Key function to a property, when using Swift?
This was previously answered for Realm Objective-C here: https://stackoverflow.com/a/29417579/599344
Essentially, if you're promoting a property to a primary key, and the property already has a unique value per object, you don't need to do anything special aside from running a normal migration.
If your new primary key property does have duplicate entries, then you'll need to change their values to something unique inside the migration block.

How can you make an association without using all entity keys in entity framework?

I'm getting more and more frustrated with EF...
I have a table called ExtendedField with:
Record
DocRef
DocType
Name
Record is the primary key
DocRef and DocType are foreign keys used to identify which Ticket they belong to
Name is the key used by the "definition" table to define what the field actually is
So basically I need 2 associations:
One between Ticket and ExtendedField
on ExtendedField.DocRef=ticket.record
and
ExtendedField.docType=HeaderDocType
One between Definition on
ExtendedField.Name=Definition.FieldName
Then I still need Record to be the primary key so I can directly access the fields.
As near as I can tell this is impossible to do in Entity Framework. For every association all the keys need to be mapped together, whereas I need two keys for one association, 1 key for another one and the actual primary key wouldn't be used in any associations.
It doesn't appear that you can define an association between fields that aren't entity keys either.
So is there any way to do this? Am I missing something?
It's a v1, bro. I myself have had some major pain with mapping of key constraints in EF. I hear that better things are coming in v2.