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.
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
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.
For school I'm working on a project in C# WPF and SQL Server. I made the database and use Linq to SQL. Now I got the following tables:
Patients
-------
ID int PK
name varchar
insurancecompany int FK
Insurancecompanies
-------
ID int PK
name varchar
insurancecompany in patients is a FK to id in insurancecompanies
I left out a lot of unnecessary columns for my question since it would take too long. So I added the database tables to my Linq to SQL database model. I created an instance to the patient class. Looking at it, I see 2 properties. One is insurancecompany, which is an int. The other is insurancecompany1, which is an insurancecompany type.
Is it safe to make the int private, or remove it? Or is there a way to make it so there's only one property?
What is happening is that database model sees that you have a foreign key relationship to Insurancecompanies, it looks at the value you've assigned it and then finds that insurancecompany and adds it as an additional property which it calls "insurancecompany1" (it would have called it "insurancecompany" but couldn't because you already have a property with that name).
This is a nice feature because it makes it easy to look at the insurance company for a given patient without needing to use joins;
var dave = patient();
//assign a patient from your database to "dave" here..
var nameOfDavesInsuranceCompany = dave.insurancecompany1.name;
If you remove the int insurancecompany you will loose this feature because the model would no longer be able to work out which insurance company to look at. You could make it private but you would loose the ability to assign an insurance company to patient by simply giving an int value (you would always have to set an insurancecompany object to insurancecompany1).
If you don't like the names, you could rename insurancecompany to something like insurancCompanyId and then call insurancecompany1 insuranceCompany.
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
In my data model I have an entity Group and another entity GroupMember. One Group consists of one or more GroupMembers, but one GroupMember can only be in one Group at the same time. So far no problem, in the database GroupMember has a foreign key to the Group's id. However now I want to have one of the members to be the "default" or "selected" member. There should always be exactly one selected member not more and not less.
I tried modelling this in Entity Framework having one 1-* association to model the group membership and one (0..1)-1 relationship to save an instance of the selected GroupMember inside of Group.
However now I obviously have the problem, that when inserting instances of Group and GroupMember I get an error that entity framework cannot determine in which order to insert the items, since Group requires a valid GroupMember as the default member, but the GroupMember cannot be inserted unless without referencing an existing Group entity. A chicken-egg problem so to say...
The easiest way would probably be to make one of the relationships optionally, but this would remove a constraint that I would like to have during normal database operation. Ideally entity framework should insert the data in any order to the database and the database should check constraint violations only at the end of the transaction.
Another way would be to model the selected member as a boolean property "IsSelected" in the GroupMember. However I'm not sure how to ensure that there is only one selected member at the same time using only the entity framework designer (I want to try to avoid working with the database directly).
Can you offer any guidance what would be the preferred way to handle this? Thanks!
The correct way to model this is with an association table:
+-------+ +--------+ +--------+
| Group |--------------| Member |-----------------| Person |
+-------+ 1 * +--------+ 1 1 +--------+
| 1 | 1
| |
| |
| 0..1 |
+--------+ |
| Leader |--------------------------------------------+
+--------+ 0..1
I'm pretending that "leader" is an accurate description of who is "special" in the group. You should try to use a more descriptive name than "selected".
The schema looks like this:
CREATE TABLE Group
(
Id int NOT NULL PRIMARY KEY,
...
)
CREATE TABLE Person
(
Id int NOT NULL PRIMARY KEY,
...
)
CREATE TABLE Member
(
PersonId int NOT NULL PRIMARY KEY
CONSTRAINT FK_Member_Person FOREIGN KEY REFERENCES Person (Id)
ON UPDATE CASCADE ON DELETE CASCADE,
GroupId int NOT NULL
CONSTRAINT FK_Member_Group FOREIGN KEY REFERENCES Group (Id)
ON UPDATE CASCADE ON DELETE CASCADE
)
CREATE INDEX IX_Member_Group ON Member (GroupId)
CREATE TABLE Leader
(
PersonId int NOT NULL PRIMARY KEY
CONSTRAINT FK_Leader_Person FOREIGN KEY REFERENCES Person (Id)
ON UPDATE CASCADE ON DELETE CASCADE,
GroupId int NOT NULL
CONSTRAINT FK_Leader_Group FOREIGN KEY REFERENCES Group (Id)
ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT U_Member_Group UNIQUE (GroupId)
)
It expresses the following information about the relationships:
A group exists, period. It may or may not have members. If it has no members, then by definition it also has no leader. It still exists, because new members might be added later.
A person exists, period. A person would not cease to exist simply because his/her group does.
A person may be a member of one and only one group.
A person may also be the leader of a group. A group can only have one leader at a time. The leader of a group may or may not be considered a member.
You may think that the constraints imposed by this relational design are significantly looser than the ones asked about in your question. And you'd be right. That's because your question is conflating the data model with the business/domain requirements.
In addition to this model you should also have several business rules, enforced by your application, such as:
If a group has no members, it is deleted/deactivated/hidden.
If a deactivated/hidden group acquires members, it is reactivated/shown.
A person must be a member of some group. This information must be supplied when a new person is added (it does not have to be an existing group, it can be a new group). If a person's membership group is deleted, this should trigger an exception process; alternatively, do not allow a group to be deleted if it still has members.
A group which has members must have a leader. If a new person is added to an empty group, that person becomes the leader. If the leader (person) is deleted, then a new leader should be automatically selected based on some criteria, or an exception process should be triggered.
Why is this the "correct" design?
First of all because it accurately portrays the independence of entities and their relationships. Groups and persons do not actually depend on each other; it is simply your business rules dictating that you are not interested in persons without a group membership or groups without any members or leaders.
More importantly because the indexing and constraints are far cleaner:
Querying the members of a group is fast.
Querying the membership(s) of a person is fast.
Querying the leader of a group is fast.
Querying the persons who are also leaders is fast.
Deleting a group will automatically remove all group memberships/leaders.
Deleting a person will automatically remove all group memberships/leaderships.
Changing a membership is still a single UPDATE statement.
Changing a leadership is still a single UPDATE statement.
SQL Server won't complain about multiple cascade paths.
Each table has at most 2 indexes, on the columns you'd expect to be indexed.
You can easily extend this design, i.e. to accommodate different types of membership.
Changes to membership/leadership will never interfere with simple queries (such as finding a person by name).
Every ORM can handle this with no trouble at all. Generally you would treat it as a many-to-many but you might be able to implement it as nullable-one-to-one.
All of the other solutions have some serious, fatal flaw:
Putting the GroupId on Person and LeaderId on Group results in a cycle that cannot be resolved except by making at least one of the columns nullable. You will also not be able to CASCADE one of the relationships.
Putting the GroupId on Person and an additional IsLeader on Person does not allow you to enforce the upper bound (1 leader per group) without a trigger. Actually, you technically can with a filtered index (SQL '08 only), but it's still wrong-headed because the IsLeader bit does not actually designate a relationship, and if you accidentally update the GroupId but forget about IsLeader then you've suddenly just made this person the leader of an entirely different group, and probably violated the at-most-one constraint.
Some people will choose to add GroupId to Person but still maintain the Leader association table. That is a better design conceptually, but since you'll likely have a CASCADE from Group to Person, you won't be able to put a two-way CASCADE on Leader as well (you'll get the "multiple cascade paths" error if you try).
Yes, I know it's a little more work and requires you to think a little harder about what your business rules are, but trust me, this is what you want to do. Anything else will only lead to pain.
The easiest way to do this is as follows:
Declare a boolean property IsSelected on the GroupMember entity.
Add a partial class declaration to the GroupMember class (all EF entity classes are declared partial, so it's easy to extend them with custom code).
Subscribe to the 'BeforeValueChanging' event of the IsSelected property (I can't remember the exact name of the event from the top of my head, but you can be sure that EF provides something like that.).
In your event handler, you then can implement the desired logic. There's no need to directly care about the database...
HTH!