I'm trying to create a table from within visual studio and update my .edmx file inside Visual Studio by right-clicking the file and selecting Update Model from Database.
My table looks like this:
CREATE TABLE [dbo].[tableName] (
[UserId] UNIQUEIDENTIFIER NOT NULL,
[CategoryId] INT NOT NULL,
CONSTRAINT [PK_responsibleUser] PRIMARY KEY NONCLUSTERED ([UserId], [pkID] ASC),
CONSTRAINT [FK_responsibleUser_user] FOREIGN KEY ([UserId]) REFERENCES [dbo].[users] ([UserId]) ON DELETE CASCADE,
CONSTRAINT [FK_categoryResponsibleUser_category] FOREIGN KEY ([CategoryId]) REFERENCES [dbo].[categories] ([CategoryId]) ON DELETE CASCADE
);
This table contains two foreign keys to the tables i want to link. After I run the script "Update Model from Database", a relation between the two tables pops up.
Now Heres the problem: I need EF to generate an instance of my class in Visual studio like this:
public virtual DbSet<tableName> TableIWantToBeGeneratedByEF { get; set; }
As I said, with the current mapping it just creates a relation between two tables. How do I alter my query when creating the table for this to happen? Can this be achieved while using two foreign keys as the primary key or what?
Just open the model designed, select all (ctrl + A), press 'delete' button to delete them, and finally right click and select Update Model from Database. This will force EF to re-generate all model.
(Or just delete all referenced tables so that they are also regenerated)
Almost forgot. It seems that it was the compound primary keys that caused the problem. I changed so both my foreign keys just acted like foreign keys and not as a combined primary key, then created a columnn named Id instead with datatype INT Identity.
Ran the script "Update Model from Database" in .edmx designer and boom, there it was.
Related
I edited the whole question because i managed to find what triggers the error so i just leave the SQL approach since it's easy to test
may cause cycles or multiple cascade paths. Specify ON DELETE NO
ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY
constraints.
DROP TABLE dbo.ProductionUnits
CREATE TABLE ProductionUnits
(
Id INT PRIMARY KEY IDENTITY,
Name NVARCHAR(50)
)
DROP TABLE Cells
CREATE TABLE Cells
(
Id INT PRIMARY KEY IDENTITY,
Name NVARCHAR(10),
ProductionUnitId INT FOREIGN KEY REFERENCES ProductionUnits(Id) ON DELETE CASCADE ON UPDATE CASCADE
)
DROP TABLE CheckLists
CREATE TABLE CheckLists
(
Id INT PRIMARY KEY IDENTITY,
Name NVARCHAR(20),
CellId INT FOREIGN KEY REFERENCES Cells(Id) ON DELETE CASCADE ON UPDATE CASCADE
)
DROP TABLE CheckListGroups
CREATE TABLE CheckListGroups
(
Id INT PRIMARY KEY IDENTITY,
Name NVARCHAR(20),
CheckListId INT FOREIGN KEY REFERENCES CheckLists(Id) ON DELETE CASCADE ON UPDATE CASCADE
)
DROP TABLE CheckListGroupItems
CREATE TABLE CheckListGroupItems
(
Id INT PRIMARY KEY IDENTITY,
Name NVARCHAR(20),
CheckListGroupId INT FOREIGN KEY REFERENCES CheckListGroups(Id) ON DELETE CASCADE ON UPDATE CASCADE
)
DROP TABLE Shifts
CREATE TABLE Shifts
(
Id INT PRIMARY KEY IDENTITY,
StartTime TIME,
EndTime TIME,
ShiftDescription NVARCHAR(20),
ProductionUnitId INT FOREIGN KEY REFERENCES ProductionUnits(Id) ON DELETE CASCADE ON UPDATE CASCADE
)
DROP TABLE ProductionRecords
CREATE TABLE ProductionRecords
(
Id INT PRIMARY KEY IDENTITY,
CreatedOn DATETIME,
CreatedBy NVARCHAR(50),
ModifiedOn DATETIME,
ModifiedBy NVARCHAR(50)
)
DROP TABLE dbo.Referencias
CREATE TABLE Referencias
(
Id INT PRIMARY KEY IDENTITY,
Name NVARCHAR(15),
)
DROP TABLE dbo.CheckListRecords
CREATE TABLE CheckListRecords
(
Id INT PRIMARY KEY IDENTITY,
Value NVARCHAR(3),
ReferenciaId INT FOREIGN KEY REFERENCES Referencias(Id) ON DELETE CASCADE ON UPDATE CASCADE,
ShiftId INT FOREIGN KEY REFERENCES Shifts(Id) ON DELETE CASCADE ON UPDATE CASCADE,
CheckListGroupItemId INT FOREIGN KEY REFERENCES dbo.CheckListGroupItems(Id) ON DELETE CASCADE ON UPDATE CASCADE,
ProductionRecordsId INT FOREIGN KEY REFERENCES ProductionRecords(Id) ON DELETE CASCADE ON UPDATE CASCADE
)
So the problem is when I add
CheckListGroupItemId INT FOREIGN KEY REFERENCES dbo.CheckListGroupItems(Id) ON DELETE CASCADE ON UPDATE CASCADE,
But i need this to know which item belongs to but this works if i delete the ON DELETE CASCADE
I'm not very experienced to SQL when it comes to foreign keys and handling cascade paths-
What should I do in this situation?
There are two paths to deleting CheckListRecords when you delete a ProductionUnits row. This is what it's complaining about.
ProductionUnits ->
Cells ->
CheckLists ->
CheckListGroups ->
CheckListGroupItems ->
CheckListRecords
...and...
ProductionUnits ->
Shifts ->
CheckListRecords
Bummer - you can't have that...an there's no real simple way to get around it :-(
It's a common occurrence. But, have hope - there's a reasonable way to deal with it...that isn't too awful. When you get a message like that, work your way backwards from the table it's griping about...and when you find multiple ON DELETE CASCADE columns in the delete path that point to the same table, you've found your culprit.
Before I suggest a solution, a couple of observations: for one thing, you've got Ids that are identity-generated. So, On Update Cascade probably shouldn't be specified in such a world because the IDs can't readily change (unless you're behaving very badly somewhere).
Another minor best-practice kinda note: specify the schema when creating the tables:
CREATE TABLE dbo.ProductionUnits
(
-- etc.
)
...and always use the schema when referring to the table in views and procedures.
Okay - so how to deal with the conflict? What you might consider doing is removing the foreign key from CheckListRecords to Shifts and instead, implement a delete trigger on Shifts that deletes the affected CheckListRecords rows. A long time ago...before there was declarative referential integrity, you had to deal with managing the relationships with triggers. It still comes in handy in places like this.
Assuming you've added the schema to the table declarations, it would be something roughly like:
create trigger [Shifts.Delete.Trigger] on dbo.Shifts for delete as
begin
set nocount on;
delete dbo.CheckListRecords where ShiftId in ( select Id from deleted );
end
See, that wasn't so bad, eh?
If you just have to update Shifts.Id for some reason, it gets a bit more complicated. You would have to have an alternate key on the Shifts table in order to implement the logic...preferably a column that you never update or at least one that is not updated when the Id gets changed. Maybe the StartTime column? You could add a uniqueidentifier column if you don't have a candidate key. For example:
CREATE TABLE Shifts
(
Id INT PRIMARY KEY IDENTITY,
StartTime TIME,
EndTime TIME,
ShiftDescription NVARCHAR(20) ,
ProductionUnitId INT FOREIGN KEY REFERENCES ProductionUnits(Id) ON DELETE CASCADE ON UPDATE CASCADE,
RowId UNIQUEIDENTIFIER
CONSTRAINT [Shifts.RowId.Default] DEFAULT ( NEWID() )
CONSTRAINT [Shifts.RowId.Unique] UNIQUE
)
Most of your views and logic would just completely ignore this column. You don't even need to let EF see it. With how I declared it, it gets set automatically on insert (similar to identity columns).
The only code that uses RowId is the update trigger:
create trigger [Shifts.Update.Trigger] on dbo.Shifts for update as
begin
set nocount on;
if update( Id ) --> just skip everything if the Id did not change
begin
update dbo.CheckListRecords
set ShiftId = i.Id
from
inserted i
inner join
deleted d
on
i.RowId = d.RowId
inner join
dbo.CheckListRecords c
on
c.ShiftId = d.Id
end
end
It's not super horrible...but not ideal. Really, if you don't have any reason to update the ID columns (and you really really shouldn't), you can skip all of this update trigger and extra column nonsense.
I think, if you have trigger-based referential integrity, you have to tell EF about it...but EF is not the way of my people...so I can't help with that particular point. But I'm almost certain it's a fairly simple declaration when you describe your data model to EF.
I need to ALTER my existing database to add a column. Consequently I also want to update the UNIQUE field to encompass that new column. I'm trying to remove the current index but keep getting the error MySQL Cannot drop index needed in a foreign key constraint
CREATE TABLE mytable_a (
ID TINYINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Name VARCHAR(255) NOT NULL,
UNIQUE(Name)
) ENGINE=InnoDB;
CREATE TABLE mytable_b (
ID TINYINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Name VARCHAR(255) NOT NULL,
UNIQUE(Name)
) ENGINE=InnoDB;
CREATE TABLE mytable_c (
ID TINYINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Name VARCHAR(255) NOT NULL,
UNIQUE(Name)
) ENGINE=InnoDB;
CREATE TABLE `mytable` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`AID` tinyint(5) NOT NULL,
`BID` tinyint(5) NOT NULL,
`CID` tinyint(5) NOT NULL,
PRIMARY KEY (`ID`),
UNIQUE KEY `AID` (`AID`,`BID`,`CID`),
KEY `BID` (`BID`),
KEY `CID` (`CID`),
CONSTRAINT `mytable_ibfk_1` FOREIGN KEY (`AID`) REFERENCES `mytable_a` (`ID`) ON DELETE CASCADE,
CONSTRAINT `mytable_ibfk_2` FOREIGN KEY (`BID`) REFERENCES `mytable_b` (`ID`) ON DELETE CASCADE,
CONSTRAINT `mytable_ibfk_3` FOREIGN KEY (`CID`) REFERENCES `mytable_c` (`ID`) ON DELETE CASCADE
) ENGINE=InnoDB;
mysql> ALTER TABLE mytable DROP INDEX AID;
ERROR 1553 (HY000): Cannot drop index 'AID': needed in a foreign key constraint
You have to drop the foreign key. Foreign keys in MySQL automatically create an index on the table (There was a SO Question on the topic).
ALTER TABLE mytable DROP FOREIGN KEY mytable_ibfk_1 ;
Step 1
List foreign key ( NOTE that its different from index name )
SHOW CREATE TABLE <Table Name>
The result will show you the foreign key name.
Format:
CONSTRAINT `FOREIGN_KEY_NAME` FOREIGN KEY (`FOREIGN_KEY_COLUMN`) REFERENCES `FOREIGN_KEY_TABLE` (`id`),
Step 2
Drop (Foreign/primary/key) Key
ALTER TABLE <Table Name> DROP FOREIGN KEY <Foreign key name>
Step 3
Drop the index.
If you mean that you can do this:
CREATE TABLE mytable_d (
ID TINYINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Name VARCHAR(255) NOT NULL,
UNIQUE(Name)
) ENGINE=InnoDB;
ALTER TABLE mytable
ADD COLUMN DID tinyint(5) NOT NULL,
ADD CONSTRAINT mytable_ibfk_4
FOREIGN KEY (DID)
REFERENCES mytable_d (ID) ON DELETE CASCADE;
> OK.
But then:
ALTER TABLE mytable
DROP KEY AID ;
gives error.
You can drop the index and create a new one in one ALTER TABLE statement:
ALTER TABLE mytable
DROP KEY AID ,
ADD UNIQUE KEY AID (AID, BID, CID, DID);
A foreign key always requires an index. Without an index enforcing the constraint would require a full table scan on the referenced table for every inserted or updated key in the referencing table. And that would have an unacceptable performance impact.
This has the following 2 consequences:
When creating a foreign key, the database checks if an index exists. If not an index will be created. By default, it will have the same name as the constraint.
When there is only one index that can be used for the foreign key, it can't be dropped. If you really wan't to drop it, you either have to drop the foreign key constraint or to create another index for it first.
Because you have to have an index on a foreign key field you can just create a simple index on the field 'AID'
CREATE INDEX aid_index ON mytable (AID);
and only then drop the unique index 'AID'
ALTER TABLE mytable DROP INDEX AID;
I think this is easy way to drop the index.
set FOREIGN_KEY_CHECKS=0; //disable checks
ALTER TABLE mytable DROP INDEX AID;
set FOREIGN_KEY_CHECKS=1; //enable checks
drop the index and the foreign_key in the same query like below
ALTER TABLE `your_table_name` DROP FOREIGN KEY `your_index`;
ALTER TABLE `your_table_name` DROP COLUMN `your_foreign_key_id`;
Dropping FK is tedious and risky. Simply create the new index with new columns and new index name, such as AID2. After the new Unique Index is created, you can drop the old one with no issue. Or you can use the solution given above to incorporate the "drop index, add unique index" in the same alter table command. Both solutions will work
In my case I dropped the foreign key and I still could not drop the index. That was because there was yet another table that had a foreign key to this table on the same fields. After I dropped the foreign key on the other table I could drop the indexes on this table.
If you are using PhpMyAdmin sometimes it don't show the foreign key to delete.
The error code gives us the name of the foreign key and the table where it was defined, so the code is:
ALTER TABLE your_table DROP FOREIGN KEY foreign_key_name;
You can show Relation view in phpMyAdmin and first delete foreign key. After this you can remove index.
You can easily check it with DBeaver. Example:
As you can see there are 3 FKs but only 2 FK indexes. There is no index for FK_benefCompanyNumber_beneficiaries_benefId as UK index provide uniqueness for that FK.
To drop that UK you need to:
DROP FK_benefCompanyNumber_beneficiaries_benefId
DROP UK
CREATE FK_benefCompanyNumber_beneficiaries_benefId
The current most upvoted answer is not complete.
One needs to remove all the foreign keys whose "source" column is also present in the UNIQUE KEY declaration.
So in this case, it is not enough to remove mytable_ibfk_1 for the error to go away, mytable_ibfk_2 and mytable_ibfk_3 must be deleted as well.
This is the complete answer:
ALTER TABLE mytable DROP FOREIGN KEY mytable_ibfk_1;
ALTER TABLE mytable DROP FOREIGN KEY mytable_ibfk_2;
ALTER TABLE mytable DROP FOREIGN KEY mytable_ibfk_3;
Its late now but I found a solution which might help somebody in future.
Just go to table's structure and drop foreign key from foreign keys list. Now you will be able to delete that column.
So i have 2 databases. DB1 and DB2. My 'discountCode' table is in DB1 and my 'AspnetUser' table is in DB2. I want to do a many to many table in DB1 between 'discountCode' table and 'AspnetUser' table so i can se that a user already have used a specific discountcode so the user cant use it twice.
I tried doing a normal many to many table between them and it went like this:
CREATE TABLE [dbo].[DiscountUser] (
[DiscountId] INT NOT NULL,
[UserId] nvarchar(128) NOT NULL,
[LanguageId] INT NOT NULL,
CONSTRAINT [PK_DiscountUser] PRIMARY KEY CLUSTERED ([DiscountId] ASC, [UserId] ASC),
CONSTRAINT [FK_DiscountUser_Discount_DiscountId] FOREIGN KEY ([DiscountId]) REFERENCES [dbo].[DiscountCode] ([Id]) ON DELETE CASCADE,
CONSTRAINT [FK_DiscountUser_AspNetUsers_Id] FOREIGN KEY ([UserId]) REFERENCES [db2].dbo.[AspNetUsers] ([id]) ON DELETE CASCADE,
CONSTRAINT [FK_DiscountUser_Language] FOREIGN KEY ([LanguageId]) REFERENCES [dbo].[Language] ([Id])
I then want to update my entity framework modeldesign so i can include this new many to many table in my c# project. So it is important that however i fix this problem i will still be able to use this many to many table like any other entity i have.
First i thought that i would put all the tables in the same database untill i asked about this problem to a friend. My friend did not have much time. All he said to me was do a join in your c# code to bring the 2 tables together. Just ask stackoverflow and they will help you how. So here i am. How do i do a join in m y c# code or is there maybe a better way to get around my problem?
You can't have foreign keys between databases - the error is pretty clear about that. But you can still join them together in a query, you just won't get protection that having them joined by a foreign key gives (e.g. without a foreign key, you can end up with orphaned entries with no data in the foreign table).
If you can have them in a single database that would be best.
This may seem a common question but I googled to find the right answer that can fix my problem and failed to do so.
I have multiple tables connected to each other by ProductID and I wish to delete all data from them when the product from main table has been deleted. i.e.
Products : ProductID - Vender - Description
ProductRatings : ProductID - Rating - VisitorsCount
ProductComments : ProductID - VisitorName - Comment
I read that for such situation a SQL trigger is used but I have no idea about it besides I might be mentioning my DataSource in ASCX.CS file in some cases and in some cases I might simply use SqlDatasoruce in ASCX file. Is there any query or stored procedure that can be used?
The easiest way to do this is to implement a foreign key relationship to ProductID and set on delete cascade. This is a general idea:
create table ProductRatings
(
ProductID int not null
foreign key references Products(ProductID) on delete cascade,
Rating int not null,
VisitorsCount int not null
)
What that does is when you delete a primary key value from the Products table, that causes SQL Server to delete all records that have a foreign key constraint to that primary key value. If you do this with your ProductComments table as well, problem solved. No need to explicitly call a DELETE on any records in the referencing tables.
And if you aren't using referential integrity...you should.
EDIT: this also holds true for UPDATEs on the primary key. You just need to specify on update cascade, and the foreign key references will update as the primary key did to ensure RI.
I have a database framework where I have two tables. The first table has a single column that is an identity and primary key. The second table contains two columns. One is a varchar primary key and the other is a nullable foreign key to the first table.
When adding the tables to the model I get the following validation error:
Condition cannot be specified for Column member 'DetailsControlSetId' because it is marked with a 'Computed' or 'Identity' StoreGeneratedPattern.
where 'DetailsControlSetId' is the second foreign key reference in the second table.
Steps to reproduce:
1) Create a new .Net 3.5 Client Profile project with Visual Studio 2010 RC.
2) Run scripts below against test database (empty database will do).
3) Create EDMX model, targeting the database created, but opt to not import any tables.
4) Update Model from Database selecting the two tables in the database (DetailsControlSet and Application).
5) Validate the EDMX model.
Table Creation Scripts:
CREATE TABLE [dbo].[DetailsControlSet](
[DetailsControlSetId] [int] IDENTITY(1,1) NOT NULL,
CONSTRAINT [PK_DetailsControlSet] PRIMARY KEY CLUSTERED
(
[DetailsControlSetId] ASC
)
)
GO
CREATE TABLE [dbo].[Application](
[ApplicationName] [varchar](50) NOT NULL,
[DetailsControlSetId] [int] NULL,
CONSTRAINT [PK_Application] PRIMARY KEY CLUSTERED
(
[ApplicationName] ASC
)
)
GO
ALTER TABLE [dbo].[Application] WITH CHECK ADD CONSTRAINT [FK_Application_DetailsControlSet] FOREIGN KEY([DetailsControlSetId])
REFERENCES [dbo].[DetailsControlSet] ([DetailsControlSetId])
ON UPDATE CASCADE
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[Application] CHECK CONSTRAINT [FK_Application_DetailsControlSet]
GO
Update Now that you've (finally!) posted steps to reproduce this, I can make the error happen on my machine. And diffing the EDMX of the "import everything at first" vs. the "import tables later" models makes the problem obvious. The "working" model has this line:
<Property Name="DetailsControlSetId" Type="int" />
The "error" model has this line:
<Property Name="DetailsControlSetId" Type="int" StoreGeneratedPattern="Identity" />
That's the only substantive difference between the two models.
So to fix this:
Right click EDMX in Solution Explorer.
Open with XML editor.
Delete StoreGeneratedPattern="Identity"
Note that the error immediately goes away.
Having this test case, I was able to do some research. It turns out this is a known bug in VS 2010 beta and was fixed a few days ago.
This article might help, was posted at ADO.NET official team blog
Foreign Key Relationships in the
Entity Framework