为什么在实体中添加具有自己ID的集合时,我总是得到主体ID而不是集合的ID?

时间:2019-09-10 03:37:26

标签: c# entity-framework asp.net-web-api

我正在将集合添加到现有数据集中。我有一个学生,其主题仍为null。因此,我正在做的就是post将收藏集放入该学生

这是我的code

[HttpPost("{id}/subjects")]
public async Task<ActionResult<object>> PostStudentSubject(string id, Subject item)
{
    // this is to get whole subject model using id
    Subject subj = await _context.Subjects.FindAsync(item.Id);

    // this is to get student model through the given id in parameter
    Student stud = await _context.FirstOrDefaultAsync(p => p.Id == id);

    if (stud == null){
        return NotFound();
    }

    // this is to remove the "subj" to avoid an Exception:
    // "The property 'Id' is part of the object's key information and cannot be modified"
    _context.Subjects.Remove(subj);
    await _context.SaveChangesAsync();

    // and this is now to add a new object Subject to the
    // collection of subjects in the student
    stud.Subjects.Add(new Subject { Id = subj.Id });
    // some subject properties are omitted...
    await _context.SaveChangesAsync();

    return Ok(stud);
}

它返回OK,但是Swagger响应返回这些:

服务器响应

  

代码->未记录,详细信息->错误:确定

回复

  

代码-> 200,说明->成功

可见的问题受试者的ID 将更改为学生的ID 。为什么会这样呢?而我在哪一部分上得到这个?

主题

    public class Subject
    {
        [Key]
        public string Id { get; set; }

        // some codes omitted ...

        [ForeignKey("Id")]
        public Student student {get; set;}
    }

学生

    public class Student
    {
        [Key]
        public string Id { get; set; }

        // some codes omitted ...

        public IList<Subject> Subjects {get; set;} = new List<Subject>();
    }

1 个答案:

答案 0 :(得分:1)

问题是外键:

    [ForeignKey("Id")]
    public Student student {get; set;}

主题表应具有一个StudentId列,以指向适用的学生。照原样,您是在告诉Subject它的PK应该是学生ID。 (就像一对一关系)

如果是代码优先,则在EF中:

public class Subject
{
    [Key]
    public string Id { get; set; } // ID for the Subject

    // some codes omitted ...

    public string StudentId { get; set; } // FK to the student.
    [ForeignKey("StudentId")]
    public Student student {get; set;}
}

但是,学生与科目之间的关系应该是多对多的关系,其中许多学生可以与许多相同的科目相关联。 (一个学生有很多科目,而一个学科有很多学生)

要执行此操作,您需要一个名为StudentSubjects之类的链接表。

StudentSubjects
StudentId [PK] [FK -> Students]
SubjectId [PK] [FK -> Subjects]

EF可以自动管理该表,只要它仅包含组合键而没有其他字段即可。否则,您需要将其定义为实体并手动提供映射。

public class Student
{
   [Key]
   public int Id { get; set; } 

   public virtual ICollection<Subject> Subjects { get; set; } = new List<Subject>();
}

public class Subject
{
   [Key]
   public int Id { get; set; } 

   public virtual ICollection<Student> Students { get; set; } = new List<Student>();
}

如果使用CodeFirst,则应建立一个StudentSubjects(或SubjectStudents)表来管理关系。否则,您可以映射HasMany.WithMany并定义表格,左右键关系...

即用于学生EntityTypeConfiguration

// EF6 Syntax. EF Core will be a tad different /w IEntityTypeConfiguration<Student> implementation.

public class StudentConfiguration : EntityTypeConfiguration<Student>
{
   public StudentConfiguration()
   {
      HasMany(x => x.Subjects)
         .WithMany(x => x.Students)
         .Map(x => x.ToTable("StudentSubjects").MapLeftKey("StudentId").MapRightKey("SubjectId"));
   }
}

我强烈建议不要对PK使用字符串。它们对于存储和索引而言相当大,您不能使用数据库端身份或诸如NewSequentialId()[GUIDs]之类的默认值