I have a question about how to realize a Table relationship in Microsoft SQL-Server 2012.
I have a Table (MyTable) which should hold a Parent/Child structure.
One Parent may have one Child and one Child only has one Parent. This is a classical one-to-one relation. The topmost entry obviously may not have a parent. (This is modelled via a nullable property)
When I try to model this in MS-SQL I receive a table as follows.
Here is my Code:
CREATE TABLE [dbo].[MyTable](
[Id] [uniqueidentifier] PRIMARY KEY NOT NULL,
[Name] [nvarchar](200) NOT NULL,
[ParentObjectId] [uniqueidentifier] NULL
)
GO
ALTER TABLE [dbo].[MyTable] WITH CHECK ADD CONSTRAINT [FK_MyTable_ParentObject] FOREIGN KEY([ParentObjectId])
REFERENCES [dbo].[MyTable] ([Id])
GO
ALTER TABLE [dbo].[MyTable] WITH CHECK ADD CONSTRAINT [Unique_ParentId] UNIQUE(ParentObjectId)
GO
ALTER TABLE [dbo].[MyTable] CHECK CONSTRAINT [FK_MyTable_ParentObject]
GO
The UNIQE Constraint should assure that there is at most one parent for one child.
BUT Entity Framework won't let me change the properties to be a one-to-one relation. It always generates a one-to-many relation.
EDIT:
The code is DB-First.
Do you have any idea on how to model this properly in MS-SQL and EntityFramework?
You can't do what you want in EF, unfortunately.
EF only supports one to one mappings when there is a shared primary key (ie both tables have to have the same primary key, and one has to be a foreign key of the other). You can't do this when using a self-referencing table for obvious reasons.
The reason EF doesn't support this is that EF doesn't support unique constraints, therefore it has no way to ensure that the 1:1 mapping is constrained. This could change because EF does now support unique indexes, however this hasn't changed the requirement for shared primary keys in one to one's.
The best you can do is create a one to many.
You should create the parent table first and then relate the child table to that so something like this
Parent Table/
Cars/
CarID/
Color/
Child Table/
Make/
MakeID/
Make/
CarID/
if you relate it that way you will achieve the correct relationship between a parent and child
Related
I am just curious to see if anyone knows of a way to insert nested objects that have auto increment keys without having to insert object one at a time.
For example, let's say I have the following tables in the database.
CREATE TABLE Analysis
(
Analysis bigint IDENTITY(1,1),
AnalysisGuid uniqueidentifier NULL,
Date date(50) NOT NULL,
CONSTRAINT PK_Analysis PRIMARY KEY(AnalysisId)
);
CREATE TABLE Scenarios
(
ScenarioId bigint IDENTITY(1,1),
AnalysisId bigint NOT NULL,
ScenarioGuid uniqueidentifier NULL,
HVACNumber int NULL,
CONSTRAINT FK_Scenarios_Analysis
FOREIGN KEY(Analysis) REFERENCES Analysis(AnalysisId)
ON DELETE CASCADE,
CONSTRAINT PK_Scenarios PRIMARY KEY(ScenarioId)
);
Where Scenario to Analysis is a M:1 relationship. And there are some other nested objects with auto increment primary key underneath the Scenarios with M:1 relationship as well.
The object that comes through the API represents an nested Analysis Object at the top level. As speed is a concern for this application, is there a way to insert the data using Entity Framework Core without going through
Insert Analysis object --> SaveChanges() --> get the Analysis primary key --> go through the Scenarios list --> insert one by one --> SaveChanges() --> get the Scenario primary key --> ...
Any help would be appreciated. Thanks!
If your EF is properly/fully set up (nav properties between parent/child, keys declared to be db generated etc) you just add the child object to the parent's nav property, add the parent to the context set and save it..
var p = new Parent();
var c1 = new Child();
var c2 = new Child();
p.Children.Add(c1);
p.Children.Add(c2);
context.Parents.Add(p);
context.SaveChanges();
After the save is done, the p.Id/c1.ParentId/c2.ParentId will be the parent ID calc'd by the db, and the c1.Id/c2.Id will also be their calc'd values.
It'll work the other way round too (adding parent to children); the change tracker isn't fussy, so long as it can reach your changes somehow
I have a DBFirst EntityFramework 6.1 solution that i'm trying to generate off of. When i add a table that only contains two foreign keys the table is turned into two associations and I can not directly access the table anymore. This is neat for navigation in the code but makes it a pain in the ass to delete records from the table.
Is there a way to prevent this behavior and gain direct access to the table as an entity?
For example i am unable to remove an entry in the association because i get this error
The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.
For example here is how my database sees the structure.
Here is how it appears in entity framework. Notice that the CorporateDataShareVisible table is missing and instead two new associations are created.
The CorporateDataShareVisible table should be able to be deleted and added to at will but any changes i make seem to stop it from working.
Add a primary key to your table that has only foreign keys. EF uses the primary key to keep track internally of the element. Without a primary key it doesnt know which element was modified and how to send that back to your RDBMS.
I prefer surrogate keys i.e auto incrementing integers.
You can also add the primary key by making it a composite key of both the foreign keys
I'm using entity framework 5 model first.
I have some entities in my model and most of them have one-to-many relationships with "no action" foreign key constraint on delete and update.
But I'm still able to delete father and child objects with no errors (on EF4 I used to get an exception warning that I cannot delete an object because there's another referencing it)
Part of the code generated by EF5 model first:
...
... Create all tables...
...
... Create all foreign key constraints ...
...
-- Creating foreign key on [TEstTela_ID] in table 'TEstPermissao'
ALTER TABLE [dbo].[TEstPermissao]
ADD CONSTRAINT [FK_TEstTelaTEstPermissao]
FOREIGN KEY ([TEstTela_ID])
REFERENCES [dbo].[TEstTela]
([ID])
ON DELETE NO ACTION ON UPDATE NO ACTION;
....
Delete Object Code:
...
EstContextDB CurrentContext = new EstContextDB(); // inherits from DbContext
CurrentContext.Set<TEstTela>().Remove(currentTEstTelaEntity);
CurrentContext.SaveChanges(); /* Exception should be thrown here
because at least one TEstPermissao object references this
currentTEstTelaEntity but it still delete the object without
errors or exceptions, and plus the TEstPermissao object
that references this currentTEstTelaEntity gets its reference as 'null' */
The problem doesn't have to do with cascading delete. You try to delete the parent TEstTelaEntity and EF sets the foreign key from the child TEstPermissao to this parent TEstTelaEntity to null (apparently the relationship is optional) and then sends an UPDATE statement for the child and a DELETE statement for the parent to the database. If cascading delete would kick in the child would be deleted as well, not only the parent. The result is consistent and valid: You just have a TEstPermissao entity in the database now without any reference to a TEstTelaEntity.
The foreign key is set to null only in the case that the child is loaded and attached to the context when you delete the parent. Otherwise you would indeed get the exception about a constraint violation you are expecting. (I believe this difference between attached vs. detached children is the same in EF 4 and EF 5.)
If you really don't want to delete a parent as long as it has any children, check with appropriate code if the parent has children or not in order to decide if Remove should be called.
I am trying to make Entity Framework inheritance between two tables.
The parent:
ParentTable
Id: int primary key
CustomAttribute: int
The Child:
ChilTable
Id: int primary key (not the same one as the parent, Child specific Id)
TCId: int foreign key to parent
SomeInformation: String
For some reasons I want to keep naming "Id" the primary key of both the ParentTable and the ChildTable. That should not bother EntityFramwork as I created a custom property with another name "CId" for the child Table:
And the Child1 table mapping is the following:
But when I "Validate" the model, VS2010 says...:
Error 3002: Problem in mapping fragments starting at line 103:Potential runtime violation of table Child1's keys (Child1.Id): Columns (Child1.Id) are mapped to EntitySet Parents's properties (Parents.CId) on the conceptual side but they do not form the EntitySet's key properties (Parents.Id).
Basically, I understand that Entity Framework sees a problem in the fact we map a table's primary key to a property that's not the key of the Entity but then how are we supposed to use inheritance?
IS inheritance only allowed when there is no primary key in the "Child" table? Should I but my primary key as "simple key"?
Thanks in advance...
EF expects the child's Id PK to also be a FK to the parent. So Child.Id is both a PK and an FK.
I have two tables that look like this:
dbo.ReviewType
ReviewTypeId INT PRIMARY KEY
ShortName CHAR(1) - Unique Index
Description
dbo.Review
ReviewId INT PRIMARY KEY
ReviewType_ShortName CHAR(1) - FK to ReviewType
...
A Review always has a ReviewType.
A ReviewType can be associated with many reviews.
I'm having trouble mapping this in Entity Framework using the Code First Fluent API.
It seems like it does not like me using a foreign key that doesn't map to the Primary Key. I'm using a foreign key to a Unique Constraint/Index instead of to the Primary Key.
How can I map this properly in Entity Framework using C#?
I should note that the way I am doing it right now is giving me this error:
System.Data.Edm.EdmAssociationConstraint: : The types of all properties in the Dependent Role of a referential constraint must be the same as the corresponding property types in the Principal Role. The type of property 'ReviewTypeCode' on entity Review' does not match the type of property 'Id' on entity 'ReviewType' in the referential constraint 'ReviewType_Reviews'.
Current version of EF doesn't support unique indexes and it cannot map relations based on non primary unique keys.