EF 6 Ghost/Random records added when saving - c#

I am having a problem that is extremely strange to me. I am working with EF6 and am modifying records in the database and then saving them. HOWEVER, on variable objects that have a foreign key, even though it exists in the db, it is randomly adding a new record to the table.
Example:
So if I have a CRec table that has a foriegn key to the Rect table, when I modify the CRec variable and save it, it is adding another entry to the Rect table.
I would add code but all I am doing is
ctxAcct.Entry(crec).State = EntityState.Modified;
Any ideas would be appreicated!
Edit
Workflow: User logins --> Opens their CRec --> edits --> clicks save.
With this being EF codefirst MVC, the below method is called from the view. oCRec is filled with foreign key values. So I will have a VendorID and a VendorID_ID. VendorID_ID is essentially a foreignkey field to the Vendor table.
When I hit save changes it is randomly adding a duplicate VendorID_ID when I haven't even touched that field.
Public void UpdateCRec(CRec oCRec)
{
ctxAcct.Entry(oCRec).State = EntityState.Deleted;
ctxAcct.SaveChanges();
//here I am making some changes and doing some calculations with other fields in the database.
//Now, after changing field values in CRec I move to the save changes method.
ctxAcct.Entry(oCRec).State = EntityState.Modified;
ctxAcct.SaveChanges();
}

Related

EF7: deleted data from relationship table on context.SaveChanges()

Forgive me for not knowing how to technically express the situation...
Main table, drop down table. Saving an Updated entity for main table (which holds FK for drop down table, deletes value for that record in the drop down table.
Why would changing a value in the main table, delete the value for the corresponding record in the drop down table?
save function
public void UpdateApplicationDetails(Application UpdatedApp)
{
AtlasContext updatecontext = new AtlasContext();
Application currAppRecord = _context.Apps.Where(a => a.Id == UpdatedApp.Id).Single();
currAppRecord = UpdatedApp;
updatecontext.Apps.Update(UpdatedApp);
updatecontext.SaveChanges();
}
Will update with necessary info if requested. Thanks for taking the time

EF5 always sets id to 0

I'm adding objects to a database where the id isn't auto-autogenerated in the database due to me wanting to specify the id myself (It's stupid I know, just play along ^^)
So I'm using Entity Framework 5 to insert the data into the database, however, eventhou I set the id before saving it, when I look in the database it's always zero. Why is this and how do I fix it?
The code is like this:
public Profile Add()
{
Profile item = new Profile()
{
id = 1,
name = "Bob"
};
db.Entry(item).State = EntityState.Added;
db.SaveChanges();
return item;
}
EDIT
I tried with db.Profiles.Add(item). Same problem
1.- In your edmx designer, right click id column, select properties
2.- In StoreGeneratedPattern select None
As PhilipStuyck said, your model was out of sync with your database, whenever you change the database you must update the model (Right click empty space in edmx designer select Update model from database).
Check that your database and your model are actually the same.
If you created your model from an existing database and then changed the database then your model is out of sync. This can also happen with code first of course.
Bottom line is that your sql will do an insert without a value for id, because EF thinks your id is going to come from the database. If you inspect the sql you will see an insert without id being provided followed with a select to get the value for id.
Conclusion is that your model and db are not the same.
Right click the designer and do update model from database.
You might have to remove your id column, or the table to begin with, EF will correct everything
You need to specify the table that you are adding it to.
so for you that would be db.NAMEOFTABLE.add(item)
normally you don't have to change the entity state to added.
Atleast I didn't have to do that in my solution.
You need to add the entity to the DbSet that represents your profiles table... something like this...
public Profile Add()
{
Profile item = db.Profiles.Create();
item.Name = "Bob";
db.Profiles.Add(item);
db.SaveChanges();
return item;
}
I prefer using the Create method however it makes no difference.
By default Id property is treated as Primary Key and as Identity by Entity Framework. So it just ignores property value, while generating sql for insert command. You should specify metadata explicitly: add [DatabaseGenerated(DatabaseGeneratedOption.None)] attribute or use method HasDatabaseGeneratedOption from FluentApi.

C# How can I clear all foreign key references in order to save the deletion of the primary key record to the database?

When I perform a delete on a primary key record it deletes the foreign key record and saves the change, but when it goes to delete the primary key record it won't let me save the deletion of the primary key record to the database. Instead it gives the following error:
Error: The primary key value cannot be deleted because references to this key still exist. [ >Foreign key constraint name = FK_PERSONID ]
According to what I've seen online I should be able to disable the EnforceConstraints either through code or through the DataSet Designer View. After doing it through code failed I tried changing the EnforceConstraints to False in the DataSet Designer View. It still gives the same error. I tried editing the foreign key constraint to do a Cascade Delete and it still gives the same error.
Trying to do it with only the Cascade Delete without the code got the same error.
This is the portion where I perform the deletes.
bizDocStartupDBDataSet1.EnforceConstraints = false;
BizDocStartupDBDataSet1.EmployeeTitlesRow oldEmployeeTitlesRow;
oldEmployeeTitlesRow = bizDocStartupDBDataSet1.EmployeeTitles.FindByPERSONIDCOMPANYID(currentPersonID,1);
oldEmployeeTitlesRow.Delete();
this.employeeTitlesTableAdapter.Update(this.bizDocStartupDBDataSet1.EmployeeTitles);
this.Validate();
this.employeeTitlesBindingSource.EndEdit();
this.tableAdapterManager.UpdateAll(this.bizDocStartupDBDataSet1);
this.peopleProfilesBindingSource.RemoveCurrent();
SaveData();
bindingNavigatorDeleteItem.Enabled = true;
bizDocStartupDBDataSet1.EnforceConstraints = true;
The SaveData function is just the standard save with a refilling of the table, but the change to the datatable can't be saved to the database because there are still references to the Foreign Key.
How do I clear out all the references to the foreign key after the key with the foreign record has been deleted so I can save the deletion of the primary key record to the database?
Foreign keys are used to prevent records from getting orphaned, so getting rid of the foreign key is only a solution when you didn't need it in the first place. Having said that, you'll have to cascade your deletes and you start with the record in the table that contains the foreign key, delete that FIRST, then delete the record with the primary key. You may have to make two dataadapters the way you're doing it, but ideally you'd do this all with a stored proc.
If you have binded tables be sure you are not delete records from the primary table unless you don't use them anymore.
if there is another table that contains a foreing key of the record you are trying to delete it you will have that problem.
Delete those record that are foreign keys of that record you want to delete and then at last delete that record you actually want to delete.
So i guess you should be careful of what you are trying to delete. Hope it helps!
And for the last question: you will have to delete all the records that are foreign.
EnforceConstraints is a property of a C# DataSet object. Modifying this value will not affect the structure or behaviors of your database.
Cascading delete is one way to solve your problem -- triggers are another. But as a general rule I don't believe you should rely on automated deletes in the database. I think it is better to use a stored procedure to manage this delete by finding all dependencies and remove them first, and then going ahead with the delete from the primary key table. This way, you know exactly what's going on in your database.
I'm surprised that you continued to get a FK error after modifying the FK with cascading delete. Maybe post the exact error and your updates to the table and we can have a better grip on what's happening?

Entity Framework: Avoid multiple saves for circular references

I'm getting this exception when calling SaveChanges on my EF ObjectContext:
Unable to determine a valid ordering for dependent operations. Dependencies may exist due to foreign key constraints
I think the problem is because I have a circular dependency on my DB model.
i.e.
Table Users
Id
ProfilePictureId
Table Pictures
Id
UserId
I'm creating a new user and setting the picture
var user = _db.Users.CreateObject();
var picture = _db.Pictures.CreateObject();
picture.User = user;
user.ProfilePicture = picture;
_db.SaveChanges();
But that throws the exception.
If I add an extra call to SaveChanges() after I set the picture's User It works just fine, I just want to avoid that double trip to the DB.
Any ideas of how to achieve this?
Thanks!
There is no way to avoid calling SaveChanges twice with your database design. You can't insert user with dependency to picture which is not inserted yet (FK will throw exception) and in the same time you can't insert picture with dependency to user which is not inserted yet (again FK will throw exception). That is not feature of EF that is feature of DB itself.
You also don't need to avoid multiple SaveChanges calls because of multiple roundtrips. EF doesn't have command batching so each insert, update or delete has its own roundtrip to database anyway.
If you want to call single SaveChanges you must change your database as follows:
Table Users
Id (PK, IDENTITY)
Table Pictures
Id (PK, FK to Users.Id, No IDENTITY)
This is native one-to-one relation where User is principal and Picture is dependent.
I would say that it's enough to make the assignment once (either setting user or picture) ie:
var user = _db.Users.CreateObject();
var picture = _db.Pictures.CreateObject();
user.ProfilePicture = picture;
_db.SaveChanges();
You are creating new entities at first two lines, and you 'link' them by user.ProfilePicture = picture. EF should handle the rest.
You don't need to setup relation from both sides.
Edit: What about this?
var user = _db.Users.CreateObject();
var picture = _db.Pictures.CreateObject();
picture.user = user;
user.ProfilePictureId = picture.Id;
_db.SaveChanges();

Inserting Rows in Relationship using a Strongly Typed DataSet

I'm using ADO.NET with a strongly typed dataset in C# (.NET 3.5). I want to insert a new row to two tables which are related in an 1:n relation.
The table Attachments holds the primary key part of the relation and the table LicenseAttachments holds the foreign key part.
AttachmentsDataSet.InvoiceRow invoice; // Set to a valid row, also referenced in InvoiceAttachments
AttachmentsDataSet.AttachmentsRow attachment;
attachment = attachmentsDataSet.Attachments.AddAttachmentsRow("Name", "Description");
attachmentsDataSet.InvoiceAttachments.AddInvoiceAttachmentsRow(invoice, attachment);
Of course when I first update the InvoicesAttachments table, I'll get a foreign key violation from the SQL server, so I tried updating the Attachments table first, which will create the rows, but will remove the attachment association in the InvoiceAttachments table. Why?
How do I solve this problem?
On the relation between the tables, ensure that the "Both Relation and Foreign Key Constraint" is selected and "Update Rule" is set to "Cascade". Combined with the "Refresh the data table" option on the adapter, after you insert your parent row, the updated ID will "Cascade" down the relationships, preventing foreign key violations in your dataset. Your child tables will then be ready to properly insert into the database.
Some things to try:
When you configure the tableadapter, did you click on advanced options, and check on "refresh data table" so that it will retrieve the identity column value?
For me sometimes I either forgot to check it, or it didn't save the configuration correctly because I didn't have my table identity increment/seed set for whatever reason. Are you using identity increment on the table?
You might also consider just re-creating the adapters for those two tables.
Usually when I go back over everything I find it was something stupid on my part.
Lastly, you might consider calling update on the Primary table, then manually grab the primary key value and manually set the value when you insert the child record. If that doesn't make sense let me know and I will post code.
You need to tell your parent table's table-adapter to refresh the
data-table after update operation.
This is how you can do that.
Open the properties of ProgramUserGroupTableAdapter -> Default Select Query -> Advnaced options. and Check the option of Refresh the data table. Save the adapter now. Now when you call update on table-adapter, the data-table will be updated [refreshed] after the update operation and will reflect the latest values from database table. if the primary-key or any coloumn is set to auto-increment, the data-table will have those latest value post recent update.
Now you can Call the update as pug.Update(dsUserGroup.ProgramUserGroup);
Read latest values from the ProgramUserGroup coloumns and assign respective values into the child table before update. This will work exactly the way you want.
alt text http://ruchitsurati.net/files/tds1.png

Categories