I'm using Entity Framework for the first time and I'm trying to create a object with a collection (and I want all the objects in the collection to be created in database as well) but I'm having some foreign keys violations.
My sample tables:
table APPOINTMENTS: ID, VAR1, DATE_APPOINTMENT
table GUESTS: ID, APPOINTMENT_ID, USER_ID, VAR2, VAR3
My test code:
DomainService aux = new DomainService();
APPOINTMENTS appointment = new APPOINTMENTS();
appointment.VAR1 = "BLA";
appointment.DATE_APPOINTMENT = new DateTime();
//The user with id = 1 is already created in the database
appointment.GUESTS.Add(new GUESTS { USER_ID = 1, VAR2 = 1, VAR3 = "F" });
aux.InsertAppointment(appointment);
At DomainService I have:
public void InsertAppointment(APPOINTMENTS appointment)
{
using (var context = this.ObjectContext)
{
context.AddToAPPOINTMENTS(appointment);
context.SaveChanges();
}
}
But I'm getting this error:
{"ORA-02291: integrity constraint (FK_GUESTS_APPOINTMENTS) violated - parent key not found"}
What am I doing wrong?
UPDATE:
To create the ID's in the database, I am using a sequence for each table and a trigger before insert to get the next value.
When I create a single object, e.g. a appointment without guests, it inserts in the database and it generates the id.
The solution to this problem:
"The ID fields that are generated from sequences won't be handled
correctly. After saving the entities the ID's will be returned as 0.
I'll fix this by manually hacking the SSDL (open your .edmx file in a
text editor) with StoreGeneratedPattern="Identity" attributes on the
ID fields (lines 6 and 16). Note that designer may rip that change out
upon future modification.
While I suppose it's not absolutely necessary it might also be prudent
to modify some type metadata such as changing "number"s to "int"s in
your SSDL and "Decimal"s to "Int32"s in your CSDL where applicable.
Frequently these don't auto-generate with the desired values
especially with XE."
#http://www.chrisumbel.com/article/oracle_entity_framework_ef
As for me, the problem was solved simply by opening diagram .edmx and changing property StoreGeneratedPattern from None to Identity for each Primary Key in each table. After saving everything was fine.
I'm using VS 2012, Entity Framework 5 (6 is not supported yet), Oracle 11.2, last ODP.NET 12, .Net 4.5
In case of EF code first approach, if this error come
(ORA-02291: integrity constraint (FK_GUESTS_APPOINTMENTS) violated -
parent key not found)
In my case there are 2 tables which have Identity columns. So I just added
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
property to my model class just above the the column which is identity column in database and it solved my problem :)
Hope this help :)
I cant see where you are setting your Primary Key (the ID property of the appointment class). Are you using a key generator on the database side? If not this should be the problem.
You're inserting a record with a foreign key value that is not found in the parent table that constraint refers back to.
Related
I recently asked a question related to this and found a solution, but realized I may have a bigger problem. If anyone can tell me if I'm able to do what I describe below without making changes to the database it would be greatly appreciated! Note: I'm new to Entity Framework.
I am trying to insert into this table (Agreement Settings) duplicate SettingsId values for a new agreement (associated with an agreementId that is illustrated in the table as a column).
However, a SettingsId is also stored in a table with these columns Algorithm Settings. The Id column represents a SettingsId and is the primary key of this table.
I only want to update the Agreement Settings table (the former table above) with these new duplicate SettingsId values and leave the latter table alone. That way I will have agreements that have duplicate SettingsId guids but only one unique representation of that guid in the Algorithm Settings table.
When I try to insert into the database using Entity Framework:
dataTransferAgreement = (await _dataTransferContext.Agreements
.AddAsync(dataTransferAgreement))
.Entity;
I get brand new guids for SettingsIds returned, although the object dataTransferAgreement has the duplicate guids as properties beforehand (they are replaced). I assume this is because Entity Framework sees these foreign keys in Agreement Settings table and their association to Algorithm Settings table (the primary key) and automatically updates the primary key and thus the associated foreign keys on its own.
I of course can't add the Algorithm Settings table properties to dataTransferAgreement, as that would cause a primary key conflict.
The question: is there any way to manually (or otherwise) insert these duplicate foreign key values into Agreement Settings table without touching the Algorithm Settings table in Entity Framework (code first)? Currently, the entity property that inserts the primary key Id for SettingsId is decorated with [Key,DatabaseGenerated(DatabaseGeneratedOption.Identity)], which is used in numerous other places in this project, so I assume I cannot change that.
Also, the entity property that associates this table in the code:
[ForeignKey(nameof(SettingsId))]
public AlgorithmSetting AlgorithmSetting { get; set; }
is not needed in my case (since I don't want to do anything with it), but I can't just remove it due to it being a domain model (again, I'm an Entity Framework newbie so if I'm wrong in any way please correct me).
In your agreements settings table, add a primary key "id", alongside the other two columns you already have. Entity Framework and relational databases aren't going to support the same primary key.
If you need to query the agreement table in the future, you can do so with any column values and just "ignore" the new primary key you added.
Happy to help further if needed.
I am using Oracle 11g database. Many tables created in database and indexer applied on Primary key. After that i used Entity Framework 5.0 to connect with database.
The issue is that , when i am saving any record in table, it doesn't send Primary key which is auto incremented value.
public HttpResponseMessage PostCategory(TBLCATEGORY tblcategory)
{
if (ModelState.IsValid)
{
db.TBLCATEGORies.Add(tblcategory);
db.SaveChanges();
int32 ID=tblcategory.ID;
return ID;
}
}
it returns ID =0;
And one more thing, while creating any column Integer in oracle, it is showing decimal in Entity Framework.
I am assuming that you have defined a sequence and a trigger in the Oracle database that does the auto increment of the ID column, so only the object in the EF model is not updated, but the actual entry in the database has the correct incremented ID value, right?
Then the problem is that the edmx model does not know that the column is actually an ID column where the value is generated in the database. You have to manually edit the edmx model. The respective column entry in the SSDL section must have the StoreGeneratedPattern property set to "Identity". This tells the model to check again the database after inserting to look up the generated ID value. However, everytime you update the model from the database, your manual changes are lost.
I have written a short blog post about it: http://blog.aitgmbh.de/2014/06/02/patch-for-entity-framework-models-based-on-oracle-databases/
And I have created a NuGet package that does everything for you whenever you build the project: http://bit.ly/1hbxIsO
This way, even after updating your edmx model, the Identity property is added again to the specified ID columns.
Could you check the following articles:
problem description:
http://connect.microsoft.com/VisualStudio/feedback/details/505178/storegeneratedpattern-property-in-ado-net-entity-model-designer-sets-cdsl-annotation-but-not-ssdl-attribute
solution to the problem:
http://visualstudiogallery.msdn.microsoft.com/a63745c0-a781-48fa-a7d2-573ee80b5d7e
My SQL table contains an Id column which is of datatype uniqueidentifier. As per advice found on SO, I've set it to have a default value of (newid()) .
Using Entity Framework 4.2 with code first, I've then mapped my Guid property to the relevant field in SQL:
[Key]
public Guid Id { get; set; }
However, whenever I try to insert an entity I receive the following exception:
The type of one of the primary key values did not match the type defined in the entity.
The argument types 'Edm.Guid' and 'Edm.String' are incompatible for this operation. Near WHERE predicate, line 1, column 61.
The only solution I can find on both here and Google is to add [DatabaseGenerated(DatabaseGeneratedOption.Identity)] as a data annotation on my Id. This doesn't change a thing - so what else could be causing this error?
Thanks in advance.
have you try set identify StoreGeneratedPattern ?
you could do it in OnModelCreate Method.
Model.Entity<Foo>().Property(o => o.Id).HasDatabaseGenerationOption(DatabaseGeneratedOption.Identity);
Using a Guid as a primary key is ill-advised if you need performance and have an index over it. The Guids are being generated with randomized values, so every time you insert a new item it will cause more work for SQL to update the index than if you used a bigint (it has to insert into different parts of the index each time instead of always appending to the end). If you need a unique identifier (such as to link items across systems that don't share the same database) then simply add it as an additional column on the table (and if you are paranoid and willing to take a perf hit on insert/update, you could additionally add a unique constraint over it).
When I create a new entity in the EF using a model generated from a database that I already created in SQL Server, obviously I have an option to set the entity's ID(Primary Key) within my code whilst declaring the new entity.
For example when I create a new instance of my 'Value' table in my code like this:
Value newValue = Value.CreateValue(int valID);
I pass in a number say 12 to valID:
Value newValue = Value.CreateValue(12);
but when I check the Value table's data in SQL Server the primary key value valID for the new entity is assigned to something other than 12, for example 7. Why is this happening?
Thanks in advance.
Check if your primary key in the database is set up as AUTONUMBER (In Enterprise Manager go to Design mode for a table and check column properties). It means that the database will disregard whatever value you are passing and generate primary key itself.
I'm a bit of a noob with DAO and SQL Server and I'm running into a problem when I'm trying to insert values into two tables that have a relation. The table Photos has a gpsId field which has a foreign key relation with the id field of the GPSLocations table. I want to create a new Photos entry linked to a new GPSLocation, so the code looks something like this:
gpsRow = dataset.GPSLocations.AddGPSLocationsRow("0.0N", "3.2W");
dataset.Photos.AddPhotosRow(#"c:\path\file.jpg", gpsRow);
tableAdapterManager.UpdateAll(dataset);
However this results in the following error:
A foreign key value cannot be inserted
because a corresponding primary key
value does not exist. [ Foreign key
constraint name = photoToGps ]
I'm using SQL Server CE. Is my understanding correct that the TableAdapterManager should be handling this hierarchical update? I just dragged these tables onto the XSD view and relied on its automatic creation of the wrapper classes. Do I need to change anything about the relation (eg to make it a Foreign Key constraint)? I've noticed that under some circumstances the gps id is positive and sometimes negative, is that relevant?
EDIT:
I've also ensured that the update property is set to CASCADE, which results in the same error. Hierarchical updates are set to true and there is a foreign key constraint between the two tables in the designer.
It's just the configuration of your data set. Doubleclick the relation beween the tables in the Visual Studio's dataset designer, choose Both Relation And Foreigh Key Constraint option and in the Update Rule field choose Cascade option and that must be it.
Some information about the subject is in MSDN, you can look here http://msdn.microsoft.com/en-us/library/bb629317.aspx and go to the related topics.
I've managed to track down the source of this problem, which boils down to a limitation of SQL Server CE compared with the full SQL Server. It turns out the major hint that something wasn't right was because the ids were negative. The ids are negative in the DataSet before the row is inserted into the database, at which point it gets resolved to a positive index. The fact that it wasn't becoming a positive index happened because the TableAdapterManager normally does a batch statement of INSERT followed by a SELECT to update the id. However, SQL Server CE doesn't support batch statements, so this requires extra code to be written so that we simulate the SELECT step by responding to the RowUpdated event. This MSDN article explains the steps.
Did you enable Hierarchical Updates as described here?
Is there a foreign key constraint between the two tables (there should be a line on the XSD designer connecting them)? Since your fields are named differently it might not have been automatically added when you dragged the tables to the design surface.
Since the column photoToGps (foreign key) depends on the primary key (id), you cannot add a photoToGps unless there is a corresponding id present. So what you need to is individual updates, instead of doing an UpdateAll. First update the GPSLocations table, and then the other table. That way, you will have an id existing before you add a photoToGPS for it.