adding object entity framework using many to many relationship - c#

I have a database like lets say a class Student and a class Course. These two have many to many relationship through a join table, holding ids of these two tables which is hidden in EF the way it supposed to.
First if I add two courses to a student. Like
John.classes.Add(math); John.classes.Add(physics) where 'John', math and physics are objects of their respective classes. When i save changes, everything happens the ways it should happen. An entry in students table, two entries in courses table and two entries in StudentCourses join table. All good.
But then, when i add another student say 'Bob' with same two classes. Bob.classes.Add(math); Bob.classes.Add(physics);It should add a row in students table adding Bob and two rows in StudentCourses join table. This doesn't happen. A row is added to students table but no rows are being added to StudentCourses table giving error of duplicate entry in courses table. Entity Framework is not adding courses because math and physics already exist in courses table but it should add two entries in StudentCourses join table.
A work around this is by adding an id column in join table and use this table as normal table and manually add entries in StudentCourses table. But i dont want to do this, I want to know the actual solution.
Thanks

i solved it by
team ct = context.teams.Find(club.id);
if (ct == null)
{ comp.teams.Add(club); }
else
{ ct.competitions.Add(comp); }
context.SaveChanges();
where comp is competition object.
I am sure this is not the actual solution but just a way around. This can't be...

Related

If one table can provide the info we need, do I need to join another table

I have two tables, table1 has a foreign key of table2. I want to get some info from table1 including a column which both table1 and table2 have. Should I join these two table to get the info?
For example:
I have two tables Course and Student, such as below
enter image description here
Solution1:
Course
|project CourseId, CouseName, StudentName, StudentId
Solution2:
Course
| project CourseId, CourseName, StudentName
| join Student
on $left.StudentId == $right.StudentId
| project CourseId, CourseName, StudentName
To get the CourseId, CourseName and StudentName, which solution is correct? Is it a good practice to pick solution2?
Please ignore the table design. It is just an example. The issue is coming from a real project that we need a query from one table which contains a foreign id and common column from other table. The query should give the common column back. Is it necessary that join the second table to get the common column?
Course table should not have Student name, it’s redundant data. And yes you can use inner join or left join on student id. Just bear in mind with the given information provided by you, the case where student id can be or cannot be null in course table.
I believe the concept of join should only be used when we need data from 2 or more tables. If you have all the required data in a single table, why you need a join. If were you, I will surely move forward with first solution. Thanks
Your tables do not follow those three normalization forms.
This is how entities and relationships should be organized if we are talking about the common scenario of designing a database for a school or something something similar to this.
There is a Many to Many relationship between Courses and Students, which allows us to associate N students with one course, and M courses with one student (one course can be attended by many students, and one student can attend many courses).
Also, this design follows the 3rd Normalization Form.
Learn more about normalization forms
Learn more about Many to Many relationships

One table for different products with same fields but with different data range?

I want to stores many different products in my database(as well as in one table). With help of inheritance (Table per Concrete Type) ,i am keeping all common fields(date,customer,orderID) in parent table and made one child table for one product .
one child table => it holds many different product with same and different fields
ProductOne = {A,B,**C**}
ProductTwo = {A,B,**D**}
ProductThree ={A,B,**F**}
Now i made TableAllProduct and Field of tables are {A,B,C,D,F}
To reason to select this design ,because i am thinking about my future new product ,For example if we got new product with these exist fields{A,B,C,D,F} ,so we should able to store new product data in TableAllProduct table without any software upgrade (instead create new table as per Inheritance approach which required new code)
TableAllProduct can hold three different product ProductOne = {A,B,C} ProductTwo = {A,B,D} ProductThree ={A,B,F}
Next step is stores Data in TableAllProduct
As per given scenario, ProductOne and ProductTwo have common field {A,B} But A field stores data from ProductOne as well as for ProductTwo
ProductOne have following option=={data__A_1,data__A_2 ,data__A_3}
ProductTwo have following option =={data__B_1,data__B_2 }
which i brings from other table (Manny to Manny)
Here we breaks rules of RDBMS ,Because I need multiple foreign key at one column ,But RDBMS doesn't supports , To delete/edit of foreign key responsibilities/function can done with DELETE_trigger(which will check record in Category table )
In this way , i can stores multiple product in table for now and future.
What is disadvantage of this approach ?
Is there any other possibilities solutions to solve this problem with better way .(I know about Entity–attribute–value model ,but in our situation ,product doesn't not changes daily /weekly bases and EVA is too complex to maintain).Thanks
You need to normalize your data.
The model you've described can work. You need to have the AllProducts table only contain the attributes(columns) in common for all of the products. Attributes like name and SKU, and maybe a reference to the vendor/supplier.
Once you have identified the common attributes, the remaining attributes can be moved into a table specific to each product. The SpecificProduct table can use the PK of the AllProducts table as a PK and FK. Every record in SpecificProduct will also have a record in the AllProducts table. The complete data for a specific product consists of the attributes from the AllProducts table joined to the columns for the specific product table.
This strategy helps to keep the AllProducts table width small when a varied subset of attributes relates to a small subset of the records in the table. By reusing the AllProducts PK as the PK/FK of the specific products table, you ensure joins performance will be good as well.

insert a row in a table that links with PK autoincrement of another table

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.

selecting a column from ms-access database which has linked tables

I am building a windows form C# app. and I use oleDb for linking access database to my app. the problem is, My access database has two tables (students,courseCodes) and one column of the "students" table(courseName) is linked to one in the "courseCode" table (the "courseCode" table contains course codes for example course code 1 is Static and I use code 1 in the "students" table for displaying Statics) now when I want to select column containing Statics using
"SELECT DISTINCT courseName FROM students";
I got the "1" instead "Statics" is there any way to retrieve "Statics" instead "1"?
I'd say your naming convention is misleading and confusing. The column should be courseIndex, not courseName.
Do a JOIN, of course (no pun intended). This query will return the distinct course names that a given student has signed up for.
select distinct courseCode.courseName
from student
join courseCode
on student.courseId = courseCode.id
where student.id = ?
Please adjust for your schema details.
Personally I think this is a poor design. A student can sign up for many courses, and a course can have many students. This is a many-to-many relationship. You need a join table; sounds like you only have a foreign key one-to-many relationship here.

C# Delete row from multiple tables

Situation: I have 3 tables:
movies (pk:movietitle, movielength....etc)
rentals (pk:personid, fk:movietitle,...etc)
rentingpeople (pk+fk:personid, name, phone...etc)
On my form there is a listbox bindingsourced with the movie titles, next to the listbox there are textboxes bindingsourced from db.movies
When someone click on the rentthismovie button I would like to delete the current rental data about that movie from table rentals and rentingpeople.
I wrote the first part and get an error because of foreign keys problem (I mentioned primary key as pk and foreign key as fk in the tables above)
var search = (from g in db.Rentals
where g.Movietitle == (string)listBox1.SelectedValue select g).First();
db.Rentals.DeleteObject(search);
db.SaveChanges();
I get an error:
The DELETE statement conflicted with the REFERENCE constraint \"FK_Rentingpeople_Rentals\". The conflict occurred in database \"C:\USERS\PC\DOCUMENTS\VISUAL STUDIO 2010\PROJECTS\FILMEK\FILMEK\BIN\DEBUG\DATABASE1.MDF\", table \"dbo.Rentingpeople\", column 'personid'.\r\nThe statement has been terminated.
Because of the primary-foreign key connection I must delete the data from rentingpeople table too as I read from this error but I can't really find a working solution.
The problem is in the db design
movies(pk:movietitle,movielength....etc)
rentals(pk:personid,fk:movietitle,...etc)
rentingpeople(pk+fk:personid,name,phone...etc)
If I got this right, movies contains the list of movies, rentingpeople is the list of people who are renting or have rented, and rentals tracks rentals. If so, rentingpeople.personid should be a pk, and rentals.personid should be an fk to the other, like this:
movies(pk:movietitle,movielength....etc)
rentals(fk:personid,fk:movietitle,...etc)
rentingpeople(pk:personid,name,phone...etc)
if you want to improve search on rentals (assuming any one person can exercise multiple rentals at the same time) you can introduce a non-unique index on personid, or a composite unique index to personid and movietitle on table rentals
You need to delete all the PK and not null references to the object you are deleting before you delete object itself.
You can change non nullable columns to nullable ones if logic allows.
var rentalsToBeDeleted = db.Rentals.Where(o =>o.movieid == movieid).ToList();
for (int i = rentalsToBeDeleted.count; i < 0; i--)
{
db.Rentals.DeleteObject(rentalsToBeDeleted.elementAt(i));
}
after all the referenced deleted.
db.SaveChanges();
writing without VS so mistakes are likely but you should get the idea.

Categories

Resources