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
Related
I have a parent-child relation among two tables named: Relation and Resource, so that Relation.RESOURCE_ID == Resource.ID
If I write my association into the dbml file, so that Relation --> Resource on RESOURCE_ID = ID then I am unable to add a Resource to a Relation entity. The cardinality of association is one to one.
tbl_res_Resource resoure = new tbl_res_Resource()
{
//ID is auto calculated
RESOURCE_KEY = "some key",
RESOURCE_TYPE = 20,
};
tbl_res_Relation relation = new tbl_res_Relation()
{
ENTITY_ID = 10,
ENTITY_TYPE_ID = 10,
//ID is auto calculated
//RESOURCE_ID should be inferred
};
relation.Resource = resoure;
context.tbl_res_Relations.InsertOnSubmit(relation);
context.SubmitChanges();
Submit changes will throw
System.Data.Linq.ForeignKeyReferenceAlreadyHasValueExceptio with the message 'Invalid operation due to the current state of the object'.
But if I go to the model (dbml) and reverse the association ( so Resource --> Relation on ID == RESOURCE_ID) then everything work fine.. without changing a line of code.
Keep in mind that all the association are defined only at dbml level, there is no foreign key into database.
What I am missing here?
What I am missing here?
Nothing, that is correct. It doesn't matter that the cardinality is one-to-one. An association in LINQ2SQL is an abstraction in the application layer that is the equivalent of defining a foreign key in the database layer. And LINQ2SQL expects you to follow the constraints of that association just the same as you would have to follow the constraints of an equivalent foreign key in the database layer.
what i don't understand is why reversing the 1-1 association (in teh dbml model) will break the association. It's a one to one, it does not have a preferred direction nor constraints at DB level.
Again this has nothing to do with cardinality (one-to-one) and associations always have a direction (parent to child(ren)) depending on how you set them up. If you look in the Properties window of the association, you'll see it says which object is the Parent and which is the Child.
In your code you're setting the relation.Resource field to a resource object, ergo saying that the resource is the parent and relation is the child:
relation.Resource = resoure;
The above is the equivalent of in the database layer making relation the child table with a foreign key defined on the Resource field relating back to the parent resource table.
If your association is defined such that relation is the parent, then your above code fails to the constraint because you have a resource child object that you're not assigning a parent to. You would need something like the following to adhere to the constraint:
resource.Relation = relation;
Is it possible to load base class and a child classes from database during runtime of an application and compile them and execute the code? With inheritance? If so how does one do it.
I've created a created a basic ERD of the database of my needs and attached to the post.
A basic structure of the database table will be as follows:
The table structure will look like:
CREATE TABLE Class
(
ClassID INT PRIMARY KEY NOT NULL,
BaseClassID INT NULL,
ClassName VARCHAR(MAX),
Code VARCHAR(MAX),
FOREIGN KEY (BaseClassID) REFERENCES Class(ClassID)
)
CREATE TABLE Item
(
ItemID int primary key NOT NULL,
ClassID int NOT NULL,
FOREIGN KEY (ClassID) REFERENCES Class(ClassID)
)
Any advice would be greatly appreciated.
I have two entities - WorkItem and TestSuite - where WorkItem is the abstract class and TestSuite implements it. The question is that how to map TestSuite properties to database columns? In case of Workitem I can do it as you can see below. But in case of TestSuite, I cannot. ReSharper does not offer the Property method.
How to map columns of derived class? In the example below: How to map WORKITEM_TEST_SUITE.TEST_SUITE_TYPE_ID column to TestSuiteEntity class? It is possible? Shall I live with the fact EF is going to create column names for me?
What I did so far?
I searched a lot, and every article deals only with the table mapping, and not the column mapping
It is important for me to have the control over column mapping.
WorkItem entity:
modelBuilder.Entity<WorkItemEntity> ( ).ToTable ( "WORKITEM" );
modelBuilder.Entity<WorkItemEntity> ( ).HasKey ( k => k.Id );
modelBuilder.Entity<WorkItemEntity> ( ).Property ( p => p.Id ).HasColumnName ( "ID" );
Workitem table:
CREATE TABLE [dbo].[WORKITEM]
(
[ID] INT NOT NULL PRIMARY KEY IDENTITY(1,1),
-- other columns
)
TestSuite entity:
modelBuilder.Entity<TestSuiteEntity> ( ).ToTable ( "WORKITEM_TEST_SUITE" );
modelBuilder.Entity<TestSuiteEntity>()//--> no property method!
Table where TestSuite stuff is stored.
CREATE TABLE [dbo].[WORKITEM_TEST_SUITE] ( [ID] INT NOT NULL PRIMARY KEY,
[TEST_SUITE_TYPE_ID] INT NOT NULL,
-- other columns )
Update:
Despite the fact that I have restarted Visual Studio for a few times to exclude the possibility intellisense / resharper haven't load the available methods, properties correctly, a day later the property method appears.
Despite the fact that I have restarted Visual Studio for a few times to exclude the possibility intellisense / resharper haven't load the available methods, properties correctly, a day later the property method appears.
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
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.