I'm trying to design a snackbar automation system (to answer the first question - No, it's not a homework, it's for learning purposes) and I have an issue with with the recipes and how to present them in the database. I have two options:
Option 1:
[Ingredients] -> [IngrID, IngrName]
[Recipe] -> [RecipeID, RecipeName]
[IngRecipe] -> [IngrID, RecipeID]
In this case the third table is a typical many-to-many table, the model looks correct and it's a piece of cake to manipulate with the data using Entity Framework. But I want to keep track of the amounts as well. Generally I use Ingredients as a table to insert the new purcheses. If the ingredient exist, just update the amount.
Option 2
Now if I add column "amount" as a column to IngRecipe, the whole idea of many-to-many table vanishes and I no longer can use the entity model to fill the fields automatically. But I can't seem to find a more apropriete place for this column. Where and how will I say "Well, get me 100 gr of chicken breast and add it to whatever recipe"
Any help is appreciated. Thanks in advance!
It's a solid model start, consider:
RecipieIngredients -> Recipe (FK), Ingredient (FK), IngredientQuantity
Key over (Recipe, Ingredient)
Note that it is still a M-M relationship (the quantity is not part of the PK nor involved in a FK), just with more relevant data for this relationship pair. The names can be changed, but at some point, this must be represented as a M-M relationship in a normalized relational model.
Don't let the framework ruin a good normalized design - and I hope EF can cope with such trivial scenarios; even LINQ2SQL can.
Related
I have two tables, one containing patient information, the other, the notes for each patient.
(One patient, many notes for a patient).
Given this, in the Designer (which you access by right-clicking on the chosen DataSet), how do I create a one-to-many relationship? I have never performed this before.
Secondly, for the patient notes table, how would I add a note to a patient record using SQL syntax? Note, this is not updating an existing one, but adding a completely new one to the patientNotes table using the unique patient ID number as the reference (so only that specific patient has that note added to them, not them and everyone else).
Very technically speaking, you don't need to do anything to create a one-to-many relationship. You just have to have the two tables set up as you have them and use them as you intend on using them. I work in data warehousing and unfortunately a great many of our relationships like this are not formalized with any sort of key or constraint.
The correct way to do it is to implement a foreign key constraint on the patient ID column on the patientNotes table. A FK will only allow you to insert data into patientNotes IF the patient ID exists in the patient table. If you would try to insert a note into your table that has a patient ID that doesn't exist in the patient table, the insert would fail and the SQL engine would give you an error. Note that the column on the patients table that you are creating the FK to must be a primary key.
Inserting data will really go as any other insert would:
INSERT INTO dbo.patientNotes (patientId, NoteText)
VALUES(4265, 'During his 8/14/2014 visit, Mr. Cottinsworth complained of chest pains. Evidently he has been wearing a lady''s corset to hide his large gut. Advised the very portly Mr. Cottinsworth to discontinue corset use'
You could toss that in a SP, put it in your code and use parameters for the patientId and NoteText, however you wanted to do it.
As far as doing this all in Visual Studio graphically, I can't be of much help there. I typically use the TSQL editor and type out what I want to do to the DB. I'm sure there are tutorials abound on how to set up FKs on Visual Studio.
Further reading:
http://msdn.microsoft.com/en-us/library/ms189049.aspx
http://www.scarydba.com/2010/11/22/do-foreign-key-constraints-help-performance/
what are the advantages of defining a foreign key
I've been used to this kind of convention before starting to work with Entity Framework/MVC:
tblMyItem (id, id_lookup1, val2, val3, val4...) - single, generic table
tblkLookup1 (id, val1, val2,...) - one to many relation table
tblmMyItemLookup2 (id, id_myitem, id_lookup2) - many to many relations table.
Recently I've found somewhere on the web that it's not good to create id column in tblmMyItemLookup2 when using Entity Framework, but I couldn't find more information on that. Could anyone please explain, why this is so significant?
When designing many-2-many relationship(i.e Student - Teacher) based on intermediate table (Student2Teacher) with only 2 foreign key columns, you'll end up having entities with navigation properties without intermediate table(no entity will be created for that table in context at all):
Student.Teachers <- EntityCollection<Teacher>
Teacher.Students <- EntityCollection<Student>
Meanwhile, if you add any extra field to your intermediate table, you'll have navigation properties pointing to intermediate entity:
Student.Student2Teacher
Teacher.Student2Teacher
making your querying uselessly more complex
In general we use lookup tables to macth associated records in two different tables that have a many to many relationship. For instance, let we have three tables: Students, Professors and StudentsProfessors. Since, a student can atten lesson that are serviced by many professors and a professor can teach more than one leasons then this is clearly a many to many relationship. So the lookup table called StudentsProfessors is used to match a student to her/his professors and vice versa. Now, the use of an id for each record of this lookup table is meaningless. We are not going to use this number anywhere. We just need to know that Student with studentId=10 is associated with professors with ids in (1,2,4,9). Just that and not the id of this record in the lookup table.
I would like to expand on this question in terms of performance. The db schema was:
Make
MakeId
MakeName
Model
ModelId
ModelName
MakeId (FK)
Vehicle
VehicleId
DatePurchased
ModelId (FK)
If I want to know the Make of a Vehicle I would need to traverse over the Model table using Vehicle.Model.Make. Let's assume I have not three but 4 or 5 tables which are connected this way, so that I would have to write e.g. InvoiceForVehicle.Vehicle.Model.Make. This would result in bad query performance, I think.
I could add an additional column MakeId (FK) to the InvoiceForVehicle table which goes directly to the make. This would mean I have duplicate data and that every time I change the relation between the InvoiceForVehicle and a vehicle I would have to update the MakeId (FK) accordingly.
InvoiceForVehicle
InvoiceId
DateCreated
VehicleId (FK)
MakeId (FK)
Is that a good idea?
For performance reasons: Maybe
For consistency reasons: No
Using what you suggest, it will be possible to have a Vehicle that's connected to a Make that doesn't correspond to (the Model of) that Vehicle!
You could try to use composite (and maybe natural) keys all the way down, with corresponding composite foreign keys. The important foreign key in this case would be the one going from Vehicle (MakeId, ModelId) to Model (MakeId, ModelId).
I doubt you will see much of a hit (if any) since you will be referencing by an ID and not doing any actual searching.
I think (based on my knowledge) that your existing model is structured more correctly then the new proposed solution. You shouldn't put yourself in a situation where you can lose data integrity like your new solution would allow.
So to answer your question. No, I don't think the new idea is a good solution. Your existing setup is more "correct" based on database normal form. Also, since Entity Framework lazy loads data you won't actually be running any queries that aren't needed.
My problem is simple but I can't seem to get EF to understand my database schema (Oracle).
Problem
I want to model more than 1 M-M relationship see diagram below:
As you can see I have a book and a journal - and I want to store a URI against both of these, by way of using a linking table (junction table, intersection table, you get it!). In this case it happens to be "www.google.com" that I want to store against Journal 16 and Book 75, they would be stored in the linking table in the follwoing format marked out in blue. For completeness I have added a green example for link with an ID of 5.
So you can see how the data knits together, I think you'll agree it's nothing too crazy.
Anyway, when I try and update EF model, it complains (in Visual Studio) with an error along the lines of.
Problem in mapping fragments starting at line 210:Foreign key constraint 'REF_URI_JOURNAL_FK1' from table REF_URI (REF_ID) to table JOURNALs (REF_ID): The columns of table REF_URI are mapped to AssociationSet BOOK_URISet's End BOOKs but the key columns of table JOURNALs are not mapped to the keys of the EntitySet BOOKs corresponding to this End.
Yeh - not really getting that error message!
I can get EF to work with 1 M-M relationship, e.g.
and it all works "hunky dory", but when I added a second M-M relationship it fell over with that error message above e.g.
Anyone know how I can get round this?
For two many-to-many relationships your need two linking tables (junction tables, intersection tables) REFBOOK_URI and REFJOURNAL_URI. I think that is what the exception is saying in a cryptic fashion. If you only had one table it would mean that if Journal 123 links to URI 789 then also Book 123 must also link to URI 789 because the REF_ID column in the link table would be a non-nullable foreign key to both the Journal and the Book table.
I have a student table and an education table, with the PK of the education table as a foreign key of the student table. However, when the education is deleted, the student no longer appears in the view. How do I solve this problem?
From the information you have given, my guess is that you have enforced referencial integrity on your database. This means that when you deleted a row in education, the students that were linked with it were also deleted.
I find that it is good practice to never delete data from tables due to other fields being dependent on them. Instead, you should have a boolean value in the table that is called 'IsDeleted' and just change that to True when you want to 'Delete' it, and when you pull data make sure you filter out anything that has the 'IsDeleted' set to 'True'
Based on what you are asking I think you should first rethink your database structure.
Answer the following questions:
Does it make sense to have a student with a non existant education?
This would be the case if you deleted an education in your Educations table but students with a FK to that education row lived on in your database. This seems to be what you are asking for but it doesn't make much sense as it doesn't mantain data integrity.
Should you be allowed to delete an education if students are enlisted in said education?
If it shouldn`t be allowed then you would only need to disable cascade deleting in your 1 to many relationship and your problem would be solved.
If an eduction is deleted, should all students assigned to said education remain in the data base?
This is what you want but with the structure of your database it is not straightforward to achieve.
Easier solution?
One would be to create 3 tables instead of 2:
Educations
Students
StudentsEducationAssignments
In 1 you store eveything that has to do ONLY with your education entities. In 2 only what has to do with your student entities (note that what type of education they choose is not something that ONLY describes the student). In 3 you store what students are assigned to what educations.
This way, if you delete an education, the students assigned to it will not be deleted, only the information that ties students to that specific education. You keep database integrity easier this way.
Hope this helps.
Maybe an OUTER JOIN instead of an INNER JOIN in your view?
If you show us the view definition we might be able to help more, without it we're just guessing.