im using Code First Entity Model with Web API Asp.Net
i need 3 tables in total
The First table(Table1) contains some information with a unique Id lets say it is like
string id
string model
The second Table (Table2)contains some information about the user. lets say it is
string Id
string name
string company
now i need a third table. which would only work as a joining table and would contain
Table1 ModelInfo
Table2 UserInfo
but it is showing me an error that table cannot be created with out a unique id. but as my architecture is i dont need a unique id
what should i do?
or do i need to change my architecture?
Your question is general EF CodeFirst Many-to-Many relationship.
Suggested readings:
EF CodeFirst - Build Many-to-Many relationships
Composite Key - question on StackOverflow
How to have Many to Many association in EF CodeFirst
Related
I am working with c# mvc using database first
I have 3 tables
Table Name (columns)
Blog (Id, BlogName, Categori_Id(i don't use this for now)),
Category (Id, CatagoryName),
MultiBlogCat (Blog_Id(Primary Key), Category_Id(Primary Key))
But "MultiBlogCat" Table does not appear in model.edmx, I cannot get data.
How can I get data from a "Course" table with linq in multiple categories.
Are you using Entity Framework? If so, EF is probably just creating collection associations on the Blob and Category classes. EF would then manage the many-to-many relationship table behind the scenes.
nHibernate probably does the same, though I'm not familiar with that particular ORM.
Tables in a many-to-many relationship are best handled by using a relationship (linking) table that only contains a Foreign Key to each table in the relationship. The relationship table itself should not have a Primary Key.
Start Edit (eesh 2017-06-18)
The above statement about the primary key is not true. A primary key should be used. The answer to the question is stated below. I have also changed the Title of this question to better reflect the problem.
Answer to Question: The linking table should have a primary key. The primary key should not be a unique generated Id column as is commonly used for other tables. Instead, it should contain a primary key that is a composite CK (candidate key) made up of the the two foreign keys that are the links for the Many-To-Many relationship. Please see the Stack Overflow question Creating composite primary key in SQL Server
Making this change causes the EF 6.0 to correctly generate the linking table as a table and not a view in the .edmx file. This change fixes the problem I was asking about and the question is answered. Thanks to Ivan Stoev and philipxy for pointing me in the right direction.
Everything below here is part of the original post which is resolved by simply creating a composite CK key for the linking table in SSMS as described above.
End Edit (eesh 2017-06-18)
When created in this fashion the relationship table does not appear in the .edmx diagram, but it is present in the edmx file. Configuring the tables in this fashion makes it easy to query the tables as each table in the relationship has a simple navigation property relating it to the other table.
Some examples of this can be found in the following links:
Entity Framework - querying a many-to-many relationship table
Entity Framework: Queries involving many to many relationship tables
Inserts and Updates should be straightforward as described in the following SO post:
Insert/Update Many to Many Entity Framework . How do I do it?
However, I found when I tried this I got the following error when trying to insert into a model that has a PackageManifest table, a Package table, and a PackageManifestAssignment table that links the two tables:
"Unable to update the EntitySet 'PackageManifestAssignment' because it has a DefiningQuery and no element exists in the element to support the current operation."
PackageManifestAssignment in the above is the linking table that links the PackageManifest table with the Package table. It only contains foreign keys for the PackageManifest and Package tables. There are no no other fields in the PackageManifestAssignment table.
Apparently this works fine when query existing relationships, but attempting to insert fails because EF 6.0 treats tables without Primary Keys as Views and, inserts are not allowed on views. Even though the association table isn't exposed to the programmer in the diagram view, it is present in the .edmx file and EF must insert a new entry in the association table for each new relationship created.
See links below for cause of error:
Entity Framework Error on SaveChanges()
It has a DefiningQuery but no InsertFunction element
Unable to update the EntitySet Table because it has a DefiningQuery and no InsertFunction element exists in the ModificationFunctionMapping element to support the current operation
In the above links an alternate solution is presented to creating a primary key for the table. Adding a primary key to the linking table would complicate CRUD for the tables in the relationship and creating relationship links. Hence, the preferred solution is to modify the .edmx file and make EF think that the table is not a view but is a table (which it is). This works. The instructions are:
Right click on the edmx file, select Open with, XML editor
Locate the entity in the edmx:StorageModels element
Remove the DefiningQuery entirely
Rename the store:Schema="dbo" to Schema="dbo" (otherwise, the code will generate an error saying the name is invalid)
Remove the store:Name property
In my particular case the change looked like:
Before Change:
<EntitySet Name="PackageManifestAssignment" EntityType="Self.PackageManifestAssignment" store:Type="Tables" store:Schema="dbo">
<DefiningQuery>SELECT
[PackageManifestAssignment].[PackageManifestId] AS [PackageManifestId],
[PackageManifestAssignment].[PackageId] AS [PackageId]
FROM [dbo].[PackageManifestAssignment] AS [PackageManifestAssignment]
</DefiningQuery>
</EntitySet>
After Change (Working Version):
<EntitySet Name="PackageManifestAssignment" EntityType="Self.PackageManifestAssignment" store:Type="Tables" Schema="dbo">
</EntitySet>
The drawback to manually making this change is that any time any table in the model is updated in the database and that change is carried over to EF using the .edmx "Update from Database/Refresh" option, the generated file (.edmx) file will overwrite the above changes to fix the error. Those changes will be required to be made manually again. This is both a cumbersome but more importantly fragile. If the change is not made future inserts for entries in the tables that use the linking table will fail. Developers making changes made many months or years down the line could easily forget this step.
Hence, the question is how to be able to keep the desired "easy to use" many-to-many relationship edit made to the .edmx file, without having to modify the .edmx file manually every time the model is updated from the database. Or, alternately is their another technique (marking the table in a certain way) or using a third party library to achieve this?
The relationship table itself should not have a Primary Key.
Every base table should have all CKs (candidate keys) declared, ie any column set(s) that have unique subrow values and that don't contain any smaller column set(s) that have unique subrow values. We can pick one as PK (primary key) and we declare any others as UNIQUE NOT NULL (which is the constraint that PK gives).
The entity id columns of an n-ary relationship/association table, aka linking/association/join table, form its PK, which, consisting of more than one column, is called composite. Per this answer:
HasKey(PackageManifestAssignment => new {
PackageManifestAssignment.PackageManifestId,
PackageManifestAssignment.PackageId
});
PS
Tables in a many-to-many relationship are best handled by using a relationship (linking) table that only contains a Foreign Key to each table in the relationship.
In general relationships/associations are n-ary. They can have attributes of their own. CKs/PKs can include entity or relationship/association (associative entity) CK/PK columns and attribute columns.
I use Entity Framework 4 on C# Winforms.
I have a SQL Server database with 2 tables like this:
Users table:
UserId (int) (PK)
UserName
Products table:
ProductId (int)(PK)
ProductTitle
UserId1 (int) (foreign key referencing `UserId` in `Users` table)
UserId2 (int) (foreign key referencing `UserId` in `Users` table)
I am modeling SQL Server database in my C# project with Entity Framework (including foreign key columns in model).
Then I get records with this code:
Entities dbEnteties = new Entities();
dbEnteties.ContextOptions.LazyLoadingEnabled = false;
var dbe = dbEnteties.Products.Include("Users");
var result = dbe.ToList();
When I get records from database I see that the UserId1 field has data but UserId2 field is Null.
What's wrong with my C# code? And how can I solve this problem?!
It's perfectly okay for you to have two foreign keys in the Products table pointing to the Users table. I do this all the time, and your reason for doing it is fine.
Since you have turned Lazy Loading off, you need to explicitly ".Include" the navigation properties if you want the query to automatically load them. You're going to have to figure out what the names are for the navigation properties that Entity Framework created automatically for you. I'm assuming you are using the "Database First" model. If that's the case, then double click on your .EDMX file and look at the Products table. You should see a section there called "Navigation Properties". They might be called "User" and "User1". If this is the case, then you need to do the following. Since you have two separate relationships between the tables, you will need two separate ".Include" statements:
dbEnteties.Products.Include(product => product.User);
dbEnteties.Products.Include(product => product.User1);
(Make sure to include using System.Data.Entity; at the very top of your file, otherwise the lambda syntax will not work.)
I have two tables
contact table
contactID (PK auto increment)
FirstName
LastName
Address
etc..
Patient table
PatientID
contactID (FK)
How can I add the contact info for Patient first, then link that contactID to Patient table
when the contactID is autoincrement (therefore not known until after the row is created)
I also have other tables
-Doctor, nurse etc
that also links to contact table..
Teacher table
TeacherID
contactID (FK)
So therefore all the contact details are located in one table.
Is this a good database design?
or is it better to put contact info for each entity in it's own table..
So like this..
Patient table
PatientID (PK auto increment)
FirstName
LastName
Address
Doctor table
DoctorID (PK auto increment)
FirstName
LastName
Address
In terms of programming, it is easier to just have one insert statement.
eg.
INSERT INTO Patient VALUES(Id, #Firstname,#lastname, #Address)
But I do like the contact table separated (since it normalize the data) but then it has issue with not knowing what the contactID is until after it is inserted, and also probably needing to do two insert statements (which I am not sure how to do)
=======
Reply to EDIT 4
With the login table, would you still have a userid(int PK) column?
E.g
Login table
UserId (int PK), Username, Password..
Username should be unique
You must first create the Contact and then once you know its primary key then create the Patient and reference the contact with the PK you now know. Or if the FK in the Patient table is nullable you can create the Patient first with NULL as the ContactId, create the contact and then update the Patient but I wouldn't do it like this.
The idea of foreign key constraints is that the row being referenced MUST exist therefore the row being referenced must exist BEFORE the row referencing it.
If you really need to be able to have the same Contact for multiple Patients then I think it's good db design. If the relationship is actually one-to-one, then you don't need to separate them into two tables. Given your examples, it might be that what you need is a Person table where you can put all the common properties of Doctors, Teachers and Patients.
EDIT:
I think it's inheritance what you are really after. There are few styles of implementing inheritance in relational db but here's one example.
Person database design
PersonId in Nurse and Doctor are foreign keys referencing Person table but they are also the primary keys of those tables.
To insert a Nurse-row, you could do like this (SQL Server):
INSERT INTO Person(FirstName) VALUES('Test nurse')
GO
INSERT INTO Nurse(PersonId, IsRegistered) VALUES(SCOPE_IDENTITY(), 1)
GO
EDIT2:
Google reveals that SCOPE_IDENTITY() equivalent in mysql is LAST_INSERT_ID() [mysql doc]
EDIT3:
I wouldn't separate doctors and nurses into their own tables so that columns are duplicated. Doing a select without inner joins would probably be more efficient but performance shouldn't be the only criteria especially if the performance difference isn't that notable. There will many occasions when you just need the common person data so you don't always have to do the joins anyway. Having each person in the same table gives the possibility to look for a person in a single table. Having common properties in a single table also allows you have to have doctor who is also a patient without duplicating any data. Later, if you want to have more common attributes, you'd need to add them to each "derived" table too and I will assure you that one day you or someone else forgets to add the properties in one of the tables.
If for some reason you are still worried about performance and are willing to sacrifice normalization to gain performance, another possibility is to have all person columns in the same table and maybe have a type column there to distinguish them and just have a lot of null columns, so that all the nurse columns are null for doctors and so on. You can read about inheritance implementation strategies to get an idea of even though you aren't using Entity Framework.
EDIT4:
Even if you don't have any nurse-specific columns at the moment, I would still create a table for them if it's even slightly possible that there will be in the future. Doing an inner join is a pretty good way to find the nurses or you could do it in the WHERE-clause (there a probably a billion ways to do this). You could have type column in the Person table but that would prevent the same person being a doctor and a patient at the same time. Also in my opinion separate tables is more "strict" and more clear for (future) developers.
I would probably make PersonId nullable in the User table since you might have users that are not actual people in the organization. For example administrators or similar service users. Think about in terms of real world entities (forget about foreign keys and nullables), is every user absolutely part of the organization? But all this is up to you and the requirements of the software. Database design should begin with an entity relationship design where you figure out the real world relationships without considering how they will be mapped to a relational database. This helps you to figure out what the actual requirements are.
Using EF Db first, I have two tables:
Table1: AppId, AppName, AppGuid [PK]
Table2: AppGuid [FK], Description, Url
Can EF create a one entity from the both?
Meaning:
App:
AppId, AppName, AppGuid, Description, Url
Update
Thanks. I have made a view. Mapped it to EF. Now I get the following error: Error 2 Error 111: Properties referred by the Principal Role App must be exactly identical to the key of the EntityType MaMDBModel.App referred to by the Principal Role in the relationship constraint for Relationship MaMDBModel.FK_AppsData_App. Make sure all the key properties are specified in the Principal Role. D:\MaM\Dev\MamAdmin_1.0\MaMDBEntityFramework\MaMModel.edmx 768 11 MaMDBEntityFramework
this is my edmx:
http://ge.tt/3rRWTOR/v/0?c
You can create a VIEW using a JOIN between these 2 tables. After this you can use that View from EF.
Do this in SQL
CREATE VIEW [ViewName] AS
SELECT *
FROM Table1 JOIN Table2 ON Table1.AppGuid = Table2.AppGuid
And import ViewName in your Entity Framework model (as you would do with a normal SQL Table) and use it to query whatever you need
EDIT: Have a look at this link for more info http://www.mssqltips.com/sqlservertip/1990/how-to-use-sql-server-views-with-the-entity-framework/