一个实体的多个外键

时间:2018-02-05 20:20:32

标签: c# asp.net entity-framework orm ef-code-first

我正在开发一个系统,志愿者可以申请成为教会仪式/约会的一部分。

我想拥有它,所以多个志愿者可以参加一个仪式,可能是1或者可能是4.我已经看到了SO上的各种例子,只使用了两个外键,但我只是不能把头包裹在两个以上。我知道我需要反向属性,但我只是感到困惑。

这是我需要的两个实体。我想我需要在志愿者中作为ICollection进行预约/仪式。我可能会离开,我不太确定。

public class Volunteer
{
    [Key]
    public int VolunteerId { get; set; }

    public string Name { get; set; }

    public string Email { get; set; }

    public bool GardaVetted { get; set; }

    public string VolunteerRole { get; set; }

    public string VolunteerPhoneNumber { get; set; }

    [ForeignKey("Church")]
    public int ChurchId { get; set; }

    [ForeignKey("Appointments")]
    public int AppointmentId { get; set; }

    //Foreign Key
    public virtual Church Church { get; set; }

    public virtual ICollection<Appointments> Appointments { get; set; }

}

public class Appointments
{
    [Key]
    public int AppointmentId { get; set; }

    public string DetailsOfAppointment { get; set; }

    public int? Fee { get; set; }

    public string RoomType { get; set; }

    public string NameOfApplicant { get; set; }

    public string ApplicantPhoneNumber { get; set; }

    public string ApplicantEmail { get; set; }

    [DataType(DataType.DateTime)]
    [DisplayFormat(ApplyFormatInEditMode = true,DataFormatString = "{0:dd/MM/yyyy HH:mm}")]
    public DateTime DateOfAppointment { get; set; }

    public string ThemeColour { get; set; }

    public Boolean Confirmed { get; set; }

    [ForeignKey("Admins")]
    public int AdministrationId { get; set; }

    [ForeignKey("Church")]
    public int ChurchId { get; set; }

    //[ForeignKey("Volunteers")]
    //public int VolunteerId { get; set; }

    public virtual Church Church { get; set; }

    public virtual Administration Admins { get; set; }

    //public virtual Volunteer Volunteers { get; set; }
}

2 个答案:

答案 0 :(得分:0)

据我所知,你的问题是,你想要从约会到志愿者的一对多关系。

只需在Appointments模型中放置志愿者的ICollection导航属性即可。这将被视为一对多的关系。就像一个约会可以有资格成为多个/多个志愿者

class Volunteer
{
  //properties
}

class Appointments
{
  //other properties
  //....
  //. . .
  //Navigation property/foreign key for Volunteers(one-many)1 appointments=many volunteers
  ICollection<Volunteer> Volunteers {get;set;}
}

答案 1 :(得分:0)

你提到了一个仪式,后来没有再提及。我认为仪式就是你在其他地方所谓的任命。

这是我从你的课程中读到的内容,以及我认为你已正确定义的内容。

你似乎有一系列的教会。每个教会都有零个或多个志愿者,每个志愿者都属于一个教会。这称为一对多关系

每个志愿者都可以有零个或多个约会。

不清楚:   - 预约只属于一名志愿者,还是几位志愿者可以参加同一个预约?   - 申请人是志愿者吗?在这种情况下:不要将志愿者属性复制给申请人   - 参加会议的所有志愿者是否属于同一个教会,或者会议的参加者是否属于不同的教会?

在我看来,来自不同教会的人们可能参加同一次会议更合乎逻辑。这意味着每个志愿者都可以参加零次或多次会议(约会),每次会议都有零个或多个志愿者参加,可能来自不同的教会:这是真正的多对多关系。

显然,教会和约会之间也存在关系。目前还不清楚这是否是主持任命的教会,或者这是否是预约的位置。无论如何,我们假设每个教会都有零个或多个任命,每个任命都只在一个教会举行

如果您关注the entity framework code first conventions,,则以下内容就足够了:

class Church
{
    public int Id {get; set;}

    // every Church has zero or more Volunteers:
    public virtual ICollection<Volunteer> Volunteers {get; set;}

    // every Church hosts zero or more Appointments:
    public virtual ICollection <Appointment> Appointments {get; set;}

    ... // other Church properties
}

class Volunteer
{
    public int Id {get; set;}

    // every Volunteer belongs to exactly one Church using foreign key
    public int ChurchId {get; set;}
    public virtual Church Church {get; set;}

    // every Volunteer has zero or more Appointments:
    public virtual ICollection<Appointment> Appointments {get; set;}

    ... // other Properties
}

class Appointment
{
    public int Id {get; set;}

    // every Appointment is attended by one or more Volunteers (many-to-many)
    public virtual ICollection<Volunteer> Volunteers {get; set;}

    // every Appointment is hosted by exactly one Church using foreign key
    public int ChurchId {get; set;}
    public virtual Church Church {get; set;}

    ... // other properties
}

class MyDbContext : DbContext
{
    public DbSet<Church> Churches {get; set;}
    public DbSet<Volunteer> Volunteers {get; set;}
    public DbSet<Appointment> Appointments {get; set;}
}

因为我遵循了实体框架惯例,所以这是所有实体框架需要知道的,我知道我计划了教会和志愿者之间的一对多以及志愿者和约会之间的多对多。实体框架将识别主键和外键,甚至可以创建junction table for your many-to-many relationship。不需要属性也不需要流畅的API。只有当您需要不同的表名或列名时,才需要属性或流畅的api。

用法:

给我所有在圣巴塞洛缪教堂举行的志愿者“约翰”任命:

var appointmentsofJohnInStBarth = dbContext.Appointments
    .Where(appointment => Appointment.Volunteer.Name = "John"
          && appointment.Church.Name = "Saint Bartholomew")
    .Select(appointment => new
    {
        StartTime = appointment.StartTime,
        EndTime = appointment.EndTime,

        Description = appointment.Description,
        Attendants = appointment.Volunteers
            .Select(volunteer => new
            {
                Name = volunteer.Name,
                Function = volunteer.Function,
                Email = volunteer.Email,
                ...
             })
             .ToList(),
    });

因为你的DbContext知道志愿者/教会/约会之间的关系,所以DbContext知道何时为一对多执行GroupJoin或者在JunctionTable上为多对多关系执行连接,没有你必须指定必须执行哪些连接。