There are the following classes

public class Act { public int Id {get;set;} public int OperationId {get;set;} public virtual Operation {get;set;} } public class Operation { public int Id {get;set;} public virtual ICollection<Program> Programs {get;set;} public virtual ICollection<Act> Acts {get;set;} } public class Program { public int Id {get;set;} public int? ActId {get;set;} public int OperationId {get;set;} public virtual Act Act {get;set;} public virtual Operation Operation {get;set;} } 

In development, I use the Code First approach, to create a many-to-many relationship between Program & Act to specified classes, I add navigation properties to Program : public virtual ICollection<Act> Acts {get;set;} , in Act : public virtual ICollection<Program> Programs {get;set;} . those. Classes began to look like this:

 public class Program { public int Id {get;set;} public int? ActId {get;set;} public int OperationId {get;set;} public virtual Act Act {get;set;} public virtual Operation Operation {get;set;} public virtual ICollection<Act> Acts {get;set;} } public class Act { public int Id {get;set;} public int OperationId {get;set;} public virtual Operation {get;set;} public virtual ICollection<Program> Programs {get;set;} } 

I add a migration ( add-migration ) and this is what is generated:

 public override void Up() { AddColumn("dbo.Acts", "Program_Id", c => c.Int()); AddColumn("dbo.Programs", "Act_Id", c => c.Int()); CreateIndex("dbo.Acts", "Program_Id"); CreateIndex("dbo.Programs", "Act_Id"); AddForeignKey("dbo.Acts", "Program_Id", "dbo.Programs", "Id"); AddForeignKey("dbo.Programs", "Act_Id", "dbo.Acts", "Id"); } 

Although I expect to create a link table of approximately the following form:

 public class ProgramActs { public int ProgramId {get;set;} public int ActId {get;set;} } 

Please tell me why this is so. Is the necessary connection not created?

PS: Entity Framework 6.1.3

PSS: Yes, I know that the connection I need can be created using fluent api , but I would like to understand why it is not created using data annotations .

    1 answer 1

    You already have the property in the Program class public virtual Act Act { get; set; } public virtual Act Act { get; set; } public virtual Act Act { get; set; } . That is, there are two parallel connections.

    When EF watches your classes - it cannot understand which property corresponds to which one. Hence the problem.

    This problem is solved with InverseProperty annotation:

     public class Program { public virtual Act Act {get;set;} public virtual ICollection<Act> Acts {get;set;} } public class Act { [InverseProperty("Acts")] public virtual ICollection<Program> Programs {get;set;} } 

    PS I do not recommend leaving the name of the navigation properties in this form - you will get confused. When there are several connections between entities, the name of the property should speak about the semantics of this relationship, and not be made on the basis of a pattern:

     public class Program { public virtual Act StartingAct {get;set;} public virtual ICollection<Act> AllActs {get;set;} } public class Act { [InverseProperty("AllActs")] public virtual ICollection<Program> UsedIn {get;set;} } 

    Otherwise, once you finish like this (real code):

     public class AttributeDefinitionRelation { // Не делайте так никогда! public virtual AttributeDefinition AttributeDefinition { get; set; } public virtual AttributeDefinition AttributeDefinition1 { get; set; } public virtual AttributeDefinition AttributeDefinition2 { get; set; } } 
    • corrected the question - Bald
    • 2
      @nikita is not going to determine the EF, but a programmer. On which you indicate, there will indicate. - Pavel Mayorov
    • one
      @ nikita if you want to get the first act in the StartingAct property, you will need to write the corresponding query: db.Programs.GroupJoin(acts, p=>p.ActId, a=>a.Id, (p,a)=>new {Program = p, FirstAct = a.FirstOrDefault()}) I hope the idea is clear - Bald
    • one
      @ nikita if I understand you correctly, then yes. those. if you didn't define ActId but created a navigation property, then EF itself would add this field - Bald
    • one
      in this particular case, I have two properties because the model changes (the structure of the tables and the connections between them), and this is due to the fact that I prefer to first create and debug and then remove unnecessary. Yes, you can create several navigation properties, but you will have to fill them out yourself , if there is a misunderstanding, then it is better to create a new question in which refer to this one - Bald