I'm new to using entity framework. I'm using EF5 to insert new data.
I get the dreaded error:
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_POSTransactionsKitMemberTaxRaw_POSTransactionsKitMemberSaleReturnRaw_KitMemberSaleReturnRowId".
I understand that to mean I don't have a row in [POSTransactionsKitMemberSaleReturnRaw]
with a primary key that matches the insert for table [POSTransactionsKitMemberTaxRaw].
I wanted EF to generate the primary keys for me and expected the missing row to have been generated automatically. Here's the code that's failing:
foreach (POSTransactionsKitMemberSaleReturnRaw posTransactionsKitMemberSaleReturnRaw in posTransactionsKitMemberRaw.POSTransactionsKitMemberSaleReturnRaws)
{
++KitMemberSaleReturnRowId;
// set temporary keys
posTransactionsKitMemberSaleReturnRaw.KitMemberSaleReturnRowId = KitMemberSaleReturnRowId;
posTransactionsKitMemberSaleReturnRaw.KitMemberRowId = KitMemberRowId;
repository.AddPOSTransactionsKitMemberSaleReturnRaw(posTransactionsKitMemberSaleReturnRaw);
foreach (POSTransactionsKitMemberTaxRaw posTransactionsKitMemberTaxRaw in posTransactionsKitMemberSaleReturnRaw.POSTransactionsKitMemberTaxRaws)
{
// set temporary keys
posTransactionsKitMemberTaxRaw.KitMemberTaxRowId = ++KitMemberTaxRowId;
posTransactionsKitMemberTaxRaw.KitMemberSaleReturnRowId = KitMemberSaleReturnRowId;
posTransactionsKitMemberTaxRaw.KitMemberKitMemberSaleReturnRowId = null;
repository.AddPOSTransactionsKitMemberTaxRaw(posTransactionsKitMemberTaxRaw);
}
}
I've validated that there are temporary primary key values in the POCO objects at run time. A sql trace of the activity shows the attempted insert value was a generated value (1439630) not the temporary value I set it to.
I've set the Auto detect changes flag off:
_context.Configuration.AutoDetectChangesEnabled = false;
The intent was to improve performance. Since this is a pure insert
there should be no way the database rows will change while I am trying to write them.
Any suggestions?
Related
I am trying to retrieve a row from database , changing certain columns value in it and adding it as new row (Entity Framework Core),
But it is giving me error
Cannot insert explicit value for identity column in table 'Audit_Schedules' when IDENTITY_INSERT is set to OFF.
This table have a Primary Key "ScheduleId"
Below is my Code
AuditSchedules _schedules = new AuditSchedules();
using (var ctx = new QuestionnaireEntities(_configuration))
{
_schedules = ctx.AuditSchedules.Where(x => x.ScheduleId == model.ScheduleID).SingleOrDefault();
_schedules.StaffId = model.TransferedAuditorCode;
_schedules.StaffName = model.TransferedAuditorName;
_schedules.FromDate = _schedules.ToDate = Convert.ToDateTime(model.TransferedScheduleDate);
ctx.AuditSchedules.Add(_schedules);
ctx.SaveChanges();
_subschedules = ctx.AuditSubSchedule.Where(x => x.SubScheduleId == model.SubScheduleID).SingleOrDefault();
_subschedules.IsHoliDay = "Y";
_subschedules.HolidayType = model.HolidayType;
_subschedules.TransferedScheduleId = _schedules.ScheduleId.ToString();
ctx.AuditSubSchedule.Update(_subschedules);
ctx.SaveChanges();
}
Error Comes In
ctx.AuditSchedules.Add(_schedules);
First I thought its conflicting in value of Schedule_ID and not able to add duplicate Primary Key , But Schedule_ID is auto generated field so this issue should not occur
I also tried setting it to different value
_schedules.ScheduleId = 0;
but it does not insert .
How Can I replicate a row with few changes in it (want to add a new row but modified values)
EF Core behavior with auto generated values on insert is different than EF6.
First, the property must have default value (0) in order to be auto generated. This allows identity inserts which was not possible in EF6.
Second, the entity being added should not be already tracked by the context, because otherwise the context keeps internally some information that the entity key has been set and will include the value (even 0) in the generated INSERT command, which in turn causes the exception you are getting.
To achieve the goal, before calling the Add method:
First make sure the entity is not tracked by either using No-tracking query when obtaining it
_schedules = ctx.AuditSchedules
.AsNoTracking() // <--
.Where(x => x.ScheduleId == model.ScheduleID)
.SingleOrDefault();
or explicitly detaching it
ctx.Entry(_schedules).State = EntityState.Detached;
Then reset the PK
_schedules.ScheduleId = 0;
The do other modifications and finally call
ctx.AuditSchedules.Add(_schedules);
This will work for simple entities w/o navigation properties / FKs. For complex entity graph you should use no tracking query, and then work with it the same way as with detached entity graphs.
The error is simple, it is because you are adding the identity insert as a part of insert. If it is identity, it has to be auto generated. So either turn off before insert and then turn it on. Or make it auto generated.
This error will be the same if you try and insert the same data from sql server.
This is basically propagated from sql server.
If you do not want an ID to be database generated, then you should use the DatabaseGenerated attribute on your model, as in
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int ScheduleId {get;set;}
If you want the identity insert to be off you can try the technique here
I am working on an existing table where as I can see there are 3(!) primary keys:
I want to copy the existing rows, alter the ctid column and then copy them again to the end of the table. I try that and I am getting the error:
Cannot add an entity with a key that is already in use.
Probably because I am copying the rows and adding them with the same primary keys. How I can solve this? Is it possible to solve it without modifying the db schema (I am thinking of adding ctid as primary key also)?
Code
var testsDefault = (from i in dc.TestUnits
where i.ctid == null
select i).ToList();
List<DAL.TestUnit> TestList = new List<DAL.TestUnit>();
foreach (var test in testsDefault)
{
DAL.TestUnit newTest = new DAL.TestUnit();
newTest.TestID = test.TestID;
newTest.PatientType = test.PatientType;
newTest.Unit = test.Unit;
newTest.ctid = "105";
TestList.Add(newTest);
}
dc.TestUnits.InsertAllOnSubmit(TestList);
dc.SubmitChanges();
You need to add ctid to your composite primary key.
ALTER TABLE TestUnits
DROP CONSTRAINT PK_WhateverYourCompositeIndexNameIs
ALTER TABLE TestUnits
ADD CONSTRAINT PK_WhateverYourCompositeIndexNameIs PRIMARY KEY (TestID, PatientType, Unit, ctid)
See: How can I alter a primary key constraint using SQL syntax?
No,it is not possible what you are trying to do without modifying the db schema. Since you are using three PK and Primary key can not be duplicate as you are trying to do. The solution to your problem is make all the row's columns unique and then add the another row but make sure all tuples must have unique entries.
The another solution to your problem is already given by Rafalon
I am trying to delete records from a DB which has no primary key. The following works:
using (myDataContext db = new myDataContext ())
{
db.ExecuteCommand("DELETE FROM myTable WHERE TradeDate = {0}", date);
}
(where date is an input to the function). But when I try convert it to LINQ
using (myDataContext db = new myDataContext ())
{
db.myTable.DeleteAllOnSubmit(db.myTable.Where(t => t.TradeDate.Date == date.Date));
db.SubmitChanges();
}
I get the following error because the table doesn't have a primary key:
Additional information: Can't perform Create, Update, or Delete operations on 'Table(myTable)' because it has no primary key.
I found the following old posts about this issue
DB:4.44:Dml Operations Using Linq Query For A Table Without Primary Key zm
Dml Operations using linq query for a table without primary key.
But I don't understand how to implement the fix they suggest (i.e. setting another key to IsPrimary).
Is there a way to do this using LINQ? Bear in mind that adding a PK to the actual SQL table is not an option (unless I just add a row counting identity column).
Without a primary key the two interfaces aren’t emitted: INotifyPropertyChanging and INotifyPropertyChanged and so LINQ to SQL doesn’t know that your record has changed. Do the following:
Open the LINQ Designer.
Open the properties window for the table you want to delete a record from.
Click on any of the columns in the entity you want to delete and you'll see a property labeled "Primary Key".
Change the value to true for column you want to use as a primary key.
Please, use the unique column as a Primary Key in the EF model.
Otherwise use DataContext.ExecuteCommand()
As others have pointed, you need to add a primary key to your table. And then execute the query.
Else you can try to delete the row manually like this:
var query = myTable.AsEnumerable().Where(r => r.Field<Date>("TradeDate") == date.Date);
foreach(var row in query.ToList())
row.Delete();
I have Table
eventid int -- not PK key but with autoincrement
jobid -- PK autoincrement disabled
userid int -- PK autoincrement disabled
To update jobID I do following:
var itemforupdate = context.table.where(n=>n.eventid == someparameter).FirstorDefault()
I get the item from database correctly, but when assigning:
itemforupdate.jobID = 5;
context.SaveChanges();
after context.SaveChanges() I get the error:
The property 'jobID' is part of the object's key information and
cannot be modified
How to update jobID from Entity Framework to solve this problem?
Updating primary key columns is not a good practice with EntityFramework. It confuses EF because it changes the identity of the object, and makes keeping the in-memory copy and the in-database copy of the data in sync very problematic. So it's not allowed.
Just don't update primary keys. Instead delete one row and insert a new one.
Alternatively you can update the primary key directly with a stored procedure or other query.
I'm using SubSonic 3.0.0.3 and I can't seem to get the ActiveRecord .tt files to recognize and generate code for the foreign keys and relationships in my SQLite database.
I think it generates everything else just fine, but after looking at other snippets online it looks like there should be more generated code than just single classes in ActiveRecord.cs and Structs.cs for each of my tables. Looking inside Structs.cs, IsForeignKey is always false for every column, even the ones I have a foreign key defined for. Additionally, each Foreign Keys region is empty within each generated ActiveRecord class.
I'm using VS2008 with references to SubSonic 3.0.0.3, System.Data.SQLite 1.0.66.0, and System.Data.SQLite.Linq 2.0.38.0 in my project. I created the database using SQLite Expert Personal 3.1.0.2076. I made some dummy tables to try to test out how SubSonic handles one:many and many:many relationships. Here's the DDL SQLite Expert spits out for my small database:
CREATE TABLE [Person] (
[PersonID] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
[PersonName] TEXT NOT NULL,
[PersonAge] INT NOT NULL
);
CREATE TABLE [Group] (
[GroupID] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
[GroupName] TEXT NOT NULL,
[GroupDescription] TEXT NOT NULL
);
CREATE TABLE [Dog] (
[DogID] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
[PersonID] INT NOT NULL CONSTRAINT [DogPersonFK] REFERENCES [Person]([PersonID]) ON DELETE CASCADE ON UPDATE CASCADE,
[DogName] TEXT NOT NULL);
CREATE TABLE [GroupPersons] (
[GroupID] INTEGER NOT NULL CONSTRAINT [GroupPersonToGroupFK] REFERENCES [Group]([GroupID]) ON DELETE CASCADE ON UPDATE CASCADE,
[PersonID] INTEGER NOT NULL CONSTRAINT [GroupPersonToPersonFK] REFERENCES [Person]([PersonID]) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT [sqlite_autoindex_GroupPersons_1] PRIMARY KEY ([GroupID], [PersonID]));
I know foreign keys are enabled and work in the database - SQLite Expert says they're on and when I change data in one place, like Person's PersonID, it does indeed change that PersonID in the Dog and GroupPersons tables. I've tried re-adding the database to the project, 'running custom tool' to get the .tt files to execute again, and even deleting them and adding them back. I can get a simple project to build that perform simple querying and insertions, however I tried just now to change the primary key of a single Person, Dog, or Group and x.Save() but System.Data.SQLite threw an exception for all three, saying SQLite error near "WHERE":syntax error. at the Save().
Any suggestions for what I should try to do next?
It seems that the FKTables attribute for each table is not assigned in the file "SQLite.ttinclude". So i add some lines of code and managed to generate foreign key code :
After line 16 (var schema = conn.GetSchema("COLUMNS");), insert :
var schemaForeignKeys = conn.GetSchema("FOREIGNKEYS");
After line 29 (tbl.Name = row["TABLE_NAME"].ToString();), insert :
tbl.FKTables = new List<FKTable>();
var foreignKeyTables = schemaForeignKeys.Select("TABLE_NAME='" + tbl.Name + "'");
foreach (var foreignKeyTable in foreignKeyTables) {
FKTable foreignKey = new FKTable();
foreignKey.ThisTable = foreignKeyTable["TABLE_NAME"].ToString();
foreignKey.ThisColumn = foreignKeyTable["FKEY_FROM_COLUMN"].ToString();
foreignKey.OtherTable = foreignKeyTable["FKEY_TO_TABLE"].ToString();
foreignKey.OtherColumn = foreignKeyTable["FKEY_TO_COLUMN"].ToString();
foreignKey.OtherClass = CleanUp(foreignKey.OtherTable);
foreignKey.OtherQueryable = foreignKey.OtherClass;
tbl.FKTables.Add(foreignKey);
}
And after line 53 (col.IsNullable=row["IS_NULLABLE"].ToString()=="True";), insert :
col.IsForeignKey = tbl.FKTables.Any(x => x.ThisColumn == col.Name);
This is for generate the foreign key code.
Moreover, you have maybe encounter a problem when you have to delete a record which has a column to be a foreign key in an other table ? For exemple :
Person(Id, Name)
Dog(Id, #PersonId)
If you have set the #PersonId foreign key on-delete action to "SET TO NULL", this won't work because foreign key support is disabled by default in SQLite 3.6.23.1 (version used by Data.SQLite 1.0.66.0).
To enable foreign key support, you have to execute this command with each connection :
PRAGMA foreign_keys = ON;
Now, this is not supported by Data.SQLite, but it will (in version 1.0.67.0, http://sqlite-dotnet2.cvs.sourceforge.net/viewvc/sqlite-dotnet2/SQLite.NET/System.Data.SQLite/SQLiteConnection.cs?r1=1.80&r2=1.81).
So you have to wait for the release or you can (like me) download the Data.SQLite source and compile the last version. It work great for me.
Good luck.
And sorry for my english :)
I'm trying to reason this. There seems to be two issues at hand:
Subsonic not recognising your foreign keys
The x.Save() function sending that error message.
SQLite will be enforcing referential integrity on its own, so while Subsonic does not see the foreign references, SQLite does, and that's why your updates go through. Subsonic does not drive SQLite, it is driving itself, which is fine.
I'm attempting to learn what SubSonic is and does. In the mean time, I have this hypothesis: the table definitions are not parsed correctly. If x.Save() is uses automatically generated SQL, it could be that the two issues are really just one.
To validate (or invalidate) this hypothesis, could you try defining the tables thus, giving the foreign keys as table attributes, not attributes of specific fields:
CREATE TABLE [Dog] (
[DogID] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
[PersonID] INTEGER NOT NULL,
[DogName] TEXT NOT NULL,
FOREIGN KEY ([PersonID]) REFERENCES [Person]([PersonID]) ON DELETE CASCADE ON UPDATE CASCADE);
CREATE TABLE [GroupPersons] (
[GroupID] INTEGER NOT NULL,
[PersonID] INTEGER NOT NULL,
FOREIGN KEY ([GroupID]) REFERENCES [Group]([GroupID]) ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY ([PersonID]) REFERENCES [Person]([PersonID]) ON DELETE CASCADE ON UPDATE CASCADE,
PRIMARY KEY ([GroupID], [PersonID]));