If a user has multiple locations
And if a user has a single role.
My table design will be like
TableUser
Userid (pk)
Username
RoleId (fk)
TableRole
RoleId (pk)
RoleName
TableLocation
LocationId (pk)
LocationName
UserLocation
LocationId (fk) (part of composite pk)
Userid (fk)(part of composite pk)
I have entity framework 4.0.
When I fetch a user entity the user entity does not have a Role object with it.
But it does have a Location object.
Why is this like this?
Is it the default behavior of entity framework?
Does it support only one-to-many relations by default?
Yes, EF doesn't support one-to-one relation modeled this way. To enforce this relation in the database you must mark RoleId in the database with unique index / constraint. EF doesn't support unique keys so it cannot model this relation as one-to-one. The only way to model one-to-one relation in EF is on top of primary keys:
Role - PK RoleId
User - PK, FK UserId
That means that instead of User.RoleId you will use User.UserId as FK to Role.
If you want to keep your current structure you must make it one-to-many relation (one role can have many users), don't expose Users navigation property on the Role and place unique key to the database. It will still allow you assigning multiple users to single role in the application but database will fire exception if you try to save it.
Related
Are there ways to make one-to-many (abstract) relation without using SQL foreign keys?
I know it could be made by joining 2 non-related tables. But is it possible to use EF Core default navigation tools?
I think you want that because you can't add a foreign-key to your entity
So, you can solve that so:
You have a entity
Group
and you want a
List<User>
but your User can't be assigned to one group.
So you create a
GroupUser
entity which has a foreign key for the
List<GroupUser>
and a navigation property to the User
This is called a many-to-many relationship
I could go into the EDMX in design view and update the cardinality (1-, 0-, etc.) of associations, but I want to know if it is alright to do that in this scenario.
I have these two tables, let's say:
User
-----
Id
UserProfile
-------------
Id
UserId
Stuff
A single user may have just one profile. Therefore, I have set a UNIQUE constraint no the UserId column in the UserProfile table. Also, UserProfile.Id is defined as a foreign key that references User.Id.
However, in the Entity Framework model, I get the following:
class User
{
ICollection<UserProfile> UserProfiles { get; set; }
}
At first, I had the UserProfile table without any primary key of its own like this:
UserProfile
--------------
UserId
Stuff
But EntityFramework made that read-only as it needed to have a primary key on every table that you want to be made writable. So, I put an Id column in the UserProfile table as well.
UPDATE
I tried setting the multiplicit/cardinality of the association between the User table and the UserProfile table in my EDMX in the designer. However, I get this error suggesting I should turn it back to what it was, i.e. a one-to-many relationship.
Running transformation: Multiplicity is not valid in Role 'UserBasicProfile'
in relationship 'FK_UserBasicProfile_User'. Because the Dependent Role
properties are not the key properties, the upper bound of the multiplicity
of the Dependent Role must be *.
I've found a way. Well, not purely a 1-1 relationship but a 1-0..1 relationship was what I was after, which, for all practical purposes is a one-to-one relationship.
If you ever fall into this trap like I described in my question, here's what you do:
1) Remove the Id field from the dependent table, in this case the UserProfile table. Therefore, do not give it a separate primary key.
2) Instead, mark the foreign key in the dependent table as its own primary key. In this case, mark the UserId field itself as the primary key of the UserProfile table.
In addition to these two, I assume, as I outlined in the question that you've got a primary and foreign key relationship between the authority (the User table in this case) and the dependent table (the UserProfile table in this example).
So, you new table structure should look like this:
User
------
Id
UserProfile
-------------
UserId (foreign key, and also the primary key of this UserProfile table)
Stuff
Entity Framework will then recognize this 1-0..1 relationship.
I have to create an entity framework model for a badly designed database. The database uses table per type inheritance but it does so with using a PK->FK relationship, not a PK->PK relationship. E.g.
Person
PersonID (PK)
Name
Employee
EmployeeID (PK)
PersonID (FK)
DateStarted
HourlyEmployee
HourlyEmployeeID (PK)
EmployeeID (FK)
HourlyRate
Obviously this is just badly designed, but I can't change it. Table per type inheritance in the entity framework essentially wants EmployeeID not to exist and the PK for Employee to be PersonID. Is it possible to create a model for this database, or do I choose another tool? any recommendations?
You will not map this as TPT inheritance because your database is configured in the way that doesn't allow you cheating EF.
If Employee.EmployeeID is auto-generated in the database and Employee.PersonID is unique (uniqueness must be enforced in the database) you should be able (not tested) to cheat EF by simply mapping:
public Employee : Person {
public DateTime DateStarted { get; set; }
}
This class will tell EF that Employee inherits key from Person (PersonID) and you will hide the real key from EF - this should work if the real key is auto-generated.
The problem is your next level of inheritance which breaks this pattern. To make this work your HourlyEmployee will have to reference PersonID - not EmployeeID. EF now doesn't know about EmployeeID existence so it even cannot map relation with HourlyEmployee.
TPT inheritance in code first has one additional limitation - PK column must have the same name in all tables.
You can create a model from the database if it exists but it might not be what you expect. EF sometimes doesn't work that great with weird database structures.
I'm new to Entity Framework and just experimenting...
Consider 3 db tables where Person is a base table. I want the Employe table to enherit from Person, storing employee specific info. It seems that EF requires that PersonId also be the PK of the Employee table, so I made EmployeeID a unique index.
Next I added a table, Application, which stores one record for every software application that the Employee supports, creating a foreign key from Application.EmployeeId to Employee.EmployeeId.
However, EF doesn't seem to recognize relationships that involve unique indexes, but only Primary Keys.
What I can do is create a relationship from Application.PersonId to Person.PersonId, however, only Employees can be responsible for an Application, so it seems more natural to me to have Application as a "child" of the Employee table rather than the Person table.
Is this possible in EF?
You can build your relation between Employee (PersonId) and Application (EmployeeId). In such case the integrity should work as you expect because only PersonIds in Employee table will be only for existing employees. EF has currently no support for unique keys.
I've got the following entities on my EDMX :-
These two entites were generated by Update Model From Database.
Now, notice how my country has the following primary key :-
Name & IsoCode
this is because each country is UNIQUE in the system by Name and IsoCode.
Now, with my States ... it's similar. Primary Key is :-
Name & CountryId
Each state is unique by name and per country.
Now, the Foreign Key for States is a CountryId. This is the sql :-
ALTER TABLE [dbo].[States] WITH CHECK ADD
CONSTRAINT [FK_States_Countries] FOREIGN KEY([CountryId])
REFERENCES [dbo].[Countries] ([CountryId])
ON UPDATE CASCADE
GO
ALTER TABLE [dbo].[States] CHECK CONSTRAINT [FK_States_Countries]
GO
Pretty simple stuff.
BUT EntityFramework doesn't like it :( It's assuming that i need to connect some properties from State entity to both primary key properties in the Country entity.
Is it possible to add an ASSOCIATION between Country and State on Country.CountryId <-> State.CountryId ... like i have mapped in my DB ?
Cheers ;)
In EF (3.5 and 4.0) FKs MUST point to Primary Keys.
But you appear to be attempting to point to a Candidate Key (i.e. [Countries].[CountryId]
I know that this is something the EF team are considering for the next version though :)
Hope this helps
Alex
For proper DB normalization, first thing is that primary keys must be only CountryId and StateId fields - the main Id fields for each table.
And ss I see from the description Name & IsoCode and Name & CountryId should be actually Unique keys, not primary.
Then the model class State should have a field:
public Country Country { get; set; }
Now EF have very good examples and since 4.3.1 + it fully supports Code first / DB first models, which I think will ease solving this.
EF 5 have more compatibility updates so I think it wont be a problem for legacy DB engines.