简体   繁体   中英

How to code (first) the following ternary relationship in MVC Entity Framework C# with fluent API?

UPDATE

It seems I did not make my self understood. I might have chosen the problem incorrectly. So I will try with another example which hopefully will illustrate better my problem.

New example: Dog breed - disease - medicine.

Description

  • A dog breed can be affected by several diseases.

  • One same disease can affect several dog breeds.

  • One medicine is effective on one or more disease for a certain dog breed

  • One medicine is effective for one or more dogs treating a certain disease

    • Thus, a medicine has a list of pairs which is necesary and, and though each pair should be unique, there is not a real relation key value because both values can be repeated.

Code

The following code works correctly with EF creating a lookup table between DogBreed and Disease as shown in the image that follows:

[Table("dog_breed")]
public DogBreed (){
    public int ID { get;set; }
    public string DogBreedName { get;set; }
    public IList<Disease> Diseases { get; set; }
}

[Table("disease")]
public Disease (){
    public int ID { get;set; }
    public string DiseaseName { get;set; }
    public IList<DogBreed> DogBreeds { get; set; }
}

DogBreed与疾病之间存在多种关系

The problem

I want to know how to add the entity medicine to my project as follows and get the EF to generate the scheme showed in the next picture.

The code could be something like this:

[Table("medicine")]
public Medicine (){
    public int ID { get;set; }
    public string MedicineName { get; set; }
    public Lookup<DogBreed,Disease> { get;set; }
}

许多与许多三元关系

But this does not generate the scheme wanted. How should I proceed?

I'd like to clarify that my doubt is how to make the code automatically generate the structure I want on my data base so I can use entity framework features seamlessly, therefore all solutions implying creating tables on the database manually, or changing the structure (ie defining a new class) have already been considered. I'm not looking for proposals on how to bypass the problem.


Old explanation

I have a simple ternary relationship in which three entities relate as I describe below in an example made up for my specific problem. The problem is I do not know how to type the code, to get the tables in my database as I expect them to be.

Entities: Student, Subject, Classroom.

  • 1 Student has several subjects.
  • 1 Subject is attended by several Students.
  • 1 Classroom can hold lessons for several subjects as well as be related to all those students which attend the classes so we would have the following diagram

关系图

So this could be easily related in a separate table which would relate the three as follows, where student 1, would take lessons from subject 13, in classroom 2.

关系表

This is the behaviour I observe for binary relation when coded the following way:

[Table("student")]
public class Student
{
[Key]
public int ID {get; set;}
public List<Subject> Subjects;
}

[Table("subject")]
public class Subject
{
[Key]
public int ID {get; set;}
public List<Student> Students;
}

In this case, when I run Add-Migration and Update-Database I get a table studentsubject which contains id's for both entities and relates the many to many relationship automatically. 表EF仅针对两个实体之间的多对多关系自动生成

So what would be the way to code the classes if the relationships in as to get that intermediate table with 3 fields, if possible? . Collections, properties, classes dictionaries...?

-The real design for my example is adding to the first listing a the following class:

[Table("classroom")]
public class Classroom
{
[Key]
public int ID {get; set;}
public KeyValuePair<Student, Subject> StudentSubject;
}
  • Any other configuration of the database gets duplicate data.
  • A dictionary value does not work (plus, it is not correct as it does not match the real meaning of the entities for there is no real key-value relation in real world between theese three)
  • In my real problem a student would have a list of subjects, and a subject a list of students. Then separately I would define Classroom and which would be identified by a unique combination of student-subject.

For the time being I will create a class which represents that ternary relationship although I feel this doesn't stick to KISS principle.

  • I am using Entity Framework 6 on windows and MySql Server.

There's no need to mention "Students" directly in "Classroom" Object,cause it has a list of "subjects" and "subject" itself has a list of "Student"

this is wrong:

public KeyValuePair<Student, Subject> StudentSubject ;

it means inserting Student to subject once in "Subject" object and once "Again" in Classroom,Why?!

You must have something like this and EF will do the magic:

[Table("classroom")] public class Classroom { [Key] public int ID {get; set;} public List<Subject> Subject; }

and it will be your each Classroom's Students for each Subject

List<Student> classroomSubjectStudents = classroom.Subjects .Where(x=>x == someSubject) .Select(x=>x.Students).ToList();

After searching for a while and waiting for some time I whent back to school and:

By definition, well normalized relationships are binary relationships. Therefore a ternary relationship as described in the example will not work with code first , nevertheless the nature of the relationship makes the binary relationships that form it (dog breed - medicine, medicine - disease, dog breed - disease) important enough to form entities by their own.

Depending on your problem, you should just choose one to form an entity. So the answer to the question would be...

To take advantage of entity framework and code first, in order to code a ternary relationship you must make the relationship between two of the parts an entity itself.

[Table("dog_breed")]
public DogBreed (){
    public int ID { get; set; }
    public string DogBreedName { get; set; }
    public List<PairMedicineDisease> PairsMedicineDisease { get; set; }
}


[Table("medicine")]
public Medicine (){
    public int ID { get;set; }
    public string MedicineName { get;set; }
}

[Table("disease")]
public Disease (){
    public int ID { get;set; }
    public string DiseaseName { get;set; }
}

[Table("pair_medicine_disease")]
public PairMedicineDisease (){
    public int ID { get;set; }
    public Disease Disease { get;set; }
    public Medicine Medicine { get;set; }
}

Thanks to all who tried to help, specially to @ Gert Arnold who pointed me in the right direction.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM