I am currently working on MVC 5 CRUD, and I just started last week. What I am encountering is an error when I use the DELETE on one of my tables because I am deleting a row of data on table A but the primary key of table A is a foreign key of table B.
Is there any way that if I delete the data on table A its corresponding data on table B will be also deleted? Thank you.
The MVC part here is irrelevant, your database design is as such that the DELETE would fail regardless of technique used.
As pointed out above by Chino you should be looking at your database, and specifically the relationships between table A and table B, and set these to cascading delete. Meaning that when a row in table A is deleted, the row in table B is deleted too (hence 'cascading')
First You Delete foreign key of table B Data And Then A Table.
Related
Tables in a many-to-many relationship are best handled by using a relationship (linking) table that only contains a Foreign Key to each table in the relationship. The relationship table itself should not have a Primary Key.
Start Edit (eesh 2017-06-18)
The above statement about the primary key is not true. A primary key should be used. The answer to the question is stated below. I have also changed the Title of this question to better reflect the problem.
Answer to Question: The linking table should have a primary key. The primary key should not be a unique generated Id column as is commonly used for other tables. Instead, it should contain a primary key that is a composite CK (candidate key) made up of the the two foreign keys that are the links for the Many-To-Many relationship. Please see the Stack Overflow question Creating composite primary key in SQL Server
Making this change causes the EF 6.0 to correctly generate the linking table as a table and not a view in the .edmx file. This change fixes the problem I was asking about and the question is answered. Thanks to Ivan Stoev and philipxy for pointing me in the right direction.
Everything below here is part of the original post which is resolved by simply creating a composite CK key for the linking table in SSMS as described above.
End Edit (eesh 2017-06-18)
When created in this fashion the relationship table does not appear in the .edmx diagram, but it is present in the edmx file. Configuring the tables in this fashion makes it easy to query the tables as each table in the relationship has a simple navigation property relating it to the other table.
Some examples of this can be found in the following links:
Entity Framework - querying a many-to-many relationship table
Entity Framework: Queries involving many to many relationship tables
Inserts and Updates should be straightforward as described in the following SO post:
Insert/Update Many to Many Entity Framework . How do I do it?
However, I found when I tried this I got the following error when trying to insert into a model that has a PackageManifest table, a Package table, and a PackageManifestAssignment table that links the two tables:
"Unable to update the EntitySet 'PackageManifestAssignment' because it has a DefiningQuery and no element exists in the element to support the current operation."
PackageManifestAssignment in the above is the linking table that links the PackageManifest table with the Package table. It only contains foreign keys for the PackageManifest and Package tables. There are no no other fields in the PackageManifestAssignment table.
Apparently this works fine when query existing relationships, but attempting to insert fails because EF 6.0 treats tables without Primary Keys as Views and, inserts are not allowed on views. Even though the association table isn't exposed to the programmer in the diagram view, it is present in the .edmx file and EF must insert a new entry in the association table for each new relationship created.
See links below for cause of error:
Entity Framework Error on SaveChanges()
It has a DefiningQuery but no InsertFunction element
Unable to update the EntitySet Table because it has a DefiningQuery and no InsertFunction element exists in the ModificationFunctionMapping element to support the current operation
In the above links an alternate solution is presented to creating a primary key for the table. Adding a primary key to the linking table would complicate CRUD for the tables in the relationship and creating relationship links. Hence, the preferred solution is to modify the .edmx file and make EF think that the table is not a view but is a table (which it is). This works. The instructions are:
Right click on the edmx file, select Open with, XML editor
Locate the entity in the edmx:StorageModels element
Remove the DefiningQuery entirely
Rename the store:Schema="dbo" to Schema="dbo" (otherwise, the code will generate an error saying the name is invalid)
Remove the store:Name property
In my particular case the change looked like:
Before Change:
<EntitySet Name="PackageManifestAssignment" EntityType="Self.PackageManifestAssignment" store:Type="Tables" store:Schema="dbo">
<DefiningQuery>SELECT
[PackageManifestAssignment].[PackageManifestId] AS [PackageManifestId],
[PackageManifestAssignment].[PackageId] AS [PackageId]
FROM [dbo].[PackageManifestAssignment] AS [PackageManifestAssignment]
</DefiningQuery>
</EntitySet>
After Change (Working Version):
<EntitySet Name="PackageManifestAssignment" EntityType="Self.PackageManifestAssignment" store:Type="Tables" Schema="dbo">
</EntitySet>
The drawback to manually making this change is that any time any table in the model is updated in the database and that change is carried over to EF using the .edmx "Update from Database/Refresh" option, the generated file (.edmx) file will overwrite the above changes to fix the error. Those changes will be required to be made manually again. This is both a cumbersome but more importantly fragile. If the change is not made future inserts for entries in the tables that use the linking table will fail. Developers making changes made many months or years down the line could easily forget this step.
Hence, the question is how to be able to keep the desired "easy to use" many-to-many relationship edit made to the .edmx file, without having to modify the .edmx file manually every time the model is updated from the database. Or, alternately is their another technique (marking the table in a certain way) or using a third party library to achieve this?
The relationship table itself should not have a Primary Key.
Every base table should have all CKs (candidate keys) declared, ie any column set(s) that have unique subrow values and that don't contain any smaller column set(s) that have unique subrow values. We can pick one as PK (primary key) and we declare any others as UNIQUE NOT NULL (which is the constraint that PK gives).
The entity id columns of an n-ary relationship/association table, aka linking/association/join table, form its PK, which, consisting of more than one column, is called composite. Per this answer:
HasKey(PackageManifestAssignment => new {
PackageManifestAssignment.PackageManifestId,
PackageManifestAssignment.PackageId
});
PS
Tables in a many-to-many relationship are best handled by using a relationship (linking) table that only contains a Foreign Key to each table in the relationship.
In general relationships/associations are n-ary. They can have attributes of their own. CKs/PKs can include entity or relationship/association (associative entity) CK/PK columns and attribute columns.
I have used SqlBulkCopy in my previous program and have enjoyed the speed-of-light advantage of its INSERTS. But then, I was only inserting things in one table only.
I now have two tables with a one-to-many association i.e. table A has a foreign key in table B. So each record in B carries an id that is the result of an insert in A.
I am wondering if there is a solution for this?
Example:
I will give a better example on this and hope we find a good solution eventually.
We have a table called Contacts. And since each contact can have zero or more Email addresses we will store those emails in a separate table called ContactEmails. So Contacts.Id will become FK on ContactEmails (say ContactEmails.ContactId).
Let's say we would like to insert 1000 Contacts and each will have zero or more Emails. And we of course want to use SqlBulkCopy for both tables.
The problem is, it is only when we insert a new Contact that we know his/her Id. Once the Contact is inserted, we know the inserted Id is e.g. 15. So we insert 3 emails for this contact and all three will have ContactEmails.ContactId value of 15. But we have no knowledge of 15 before the contact is inserted into the database.
We can insert all contacts as bulk into the table. But when it comes to their email, the connection is lost because emails do not know their own contacts.
Disable the constraints (foreign key) before bulk insert. Then enable it again.
Make sure you do not have referential integrity violations.
You can disable FK and CHECK constraints using below query:
ALTER TABLE foo NOCHECK CONSTRAINT ALL
or
ALTER TABLE foo NOCHECK CONSTRAINT CK_foo_column
Primary keys and unique constraints can not be disabled, but this should be OK if I've understood you correctly.
I'm having issues adding a Foreign Key to link 2 existing tables together. Table A has data, and I need it to reference Table B (which also has data).
I will need to insert a row (or rows) into Table B which Table A will reference.
In this case it is acceptable to insert a row into Table B and then use that as the default value for the migration. That would require that I know the ID of the row that I'm inserting.
I think that I can handle everything except figuring out the ID of the row that I insert into Table B.
Is it possible to return data inside of Migrations?
Sorry for the title but I didn't know how to name it..
I'm using C# and have a WinForms application
I have 2 tables, each of them have a primary key, those 2 tables are strangers.
It means that I have a third table that connects between them.
the third table have as columns : table's A primary key and table's B primary key.
I just want to know that if I'm deleting one row from the third table, is the related
data from table A and B will be also deleted?
If you created a foreign key constraint with the ON DELETE CASCADE option, then yes, it will delete the related rows in other tables.
If you created a foreign key constraint WITHOUT the ON DELETE CASCADE option, then the DBMS will prevent you from deleting the original row at all.
If you did not create a foreign key constraint then only the original row will be deleted.
See this SO answer for example usage of the cascading delete option.
No, it doesn't your third table is just associate table which stores references of table A and B.
But it will have different functionality other way, if a record is deleted in table A and it has any references in associate table C. Depending upon your cascade options, record in table C will also be deleted. If there are no cascade options mentioned, it gives exception.
Sql Server wouldn't let you delete the row from 3rd table because of a Foreign Key constraint. You'd have to delete the values referencing the 3rd table from table A and B first and then delete from your 3rd table.
No, as the third table is an association table of table a and table b, no records from table a and table b will be deleted, if the deletion is on third table.
Is there a simple solution for duplicating table rows in SQL Server as well as all table rows with foreign keys pointing to the cloned table row? I've got a "master" table and a bunch of "child" tables which have a foreign key into the ID of the master table. I need to not only create a perfect copy of the master table, but clone each and every child table referencing the master table. Is there a simpler way to do this than creating a new row in the master table, copying in the information from the row to be cloned, then going through each child table and doing the same with each row pointing to the cloned row in the master table?
I'm using a SQL Server 2005 Database accessed through C# ASP.net MVC 1.0.
If by "simple" you mean is there is a procedure that can be called to do it, no there is not. However, you can use the INFORMATION_SCHEMA views such as INFORMATION_SCHEMA.COLUMNS and INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS to query for the columns in a table or the list of related tables and dynamically build your INSERT statements to copy one row to another. Of course, this does not account for other uniqueness constraints that might be on the tables (e.g. a table with a Name column which requires that the values be unique).