我碰到了那个question。我的问题很相似。
我有两个EF班的约会和工作。它们之间具有一对多的关系。
public class Appointment
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
public int AppointmentID { get; set; }
public int AppointmentStatus { get; set; }
public string Remarks { get; set; }
public ICollection<Job> Job {get; set; }
}
public class Job
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int JobId { get; set; }
public string JobName { get; set; }
public string JobDescription { get; set; }
public short JobMode { get; set; }
public virtual Appointment Appointments { get; set; }
}
当我尝试将作业添加到约会实例时,我收到nullreferenceexception。由于约会的Job属性返回null。到目前为止很正常。
为处理该异常,我尝试在父项的约束中添加一个块,以在创建约会时初始化新的Job项目。
public Appointment()
{
if (this.Job == null)
{
this.Job = new Collection<Job>();
}
}
那时候,我不再得到nullreferenceexception,但是该解决方案导致重复的Job项目。成功创建了新约会,但不是我选择的工作(!)。实际上是我选择的工作的一个实例。每次创建新的工作实例并将其与新创建的约会相关联。
答案 0 :(得分:1)
我建议您坚持使用Entity Framework Code-First conventions。它使您和以后阅读您代码的人的生活更加轻松。
在您的情况下,这意味着每个Appointment
都具有零个或多个Jobs
,并且每个Job
都使用外键恰好属于一个Appointment
。
class Appointment
{
public int Id {get; set;}
// every Appointment has zero or more Jobs:
public virtual ICollection<Job> Jobs {get; set;}
...
}
class Job
{
public int Id {get; set;}
// every Job belongs to exactly one Appointment using foreign key:
public int AppointmentId {get; set;}
public virtual Appointment Appointment {get; set;}
...
}
因为我坚持约定,所以实体框架能够检测一对多关系。它检测主键和外键:不需要属性,也不需要流畅的API。
在Entity Framework中,表中的列是非虚拟属性 在你的课上。表之间的关系(一对多,多对多, ...)被标记为虚拟:它们不是您表中的真实项目
这只是一个建议,如果您有充分的理由偏离约定,那么您当然可以这样做。
但是,必须将表之间的关系定义为虚拟。您还需要定义外键。
完成此操作后,您提取的约会将没有空的职位:
var fetchedAppointment = dbContext.Appointments
.Where(appointment => appointment.Id = ...)
.FirstOrDefault();
// fetchedAppointment.Jobs is not null!
// add a new Job:
fetchedAppointment.Jobs.Add(new Job()
{
// no need to fill the Id, nor the foreign key. Entity Framework will do that for you
JobName = ...,
JobDescription = ...,
...
});
dbContext.SaveChanges();
但是,如果要添加一个或多个职位的新约会,则必须自己添加。您可以使用数组或列表,没关系,只要它实现ICollection<Job>
var addedAppointment = dbContext.Appointments.Add(new Appointment()
{
// no need to fill the Id: entity framework will do that for you
AppointmentStatus = ...
Remarks = ...
Jobs = new List<Job>()
{
// again: no need to fill the Id, nor the foreign key.
// Entity Framework will do that for you
new Job()
{
JobName = ...,
JobDescription = ...,
},
new Job()
{
JobName = ...,
JobDescription = ...,
},
...
},
});
// if you want, you can also add a Job here:
addedAppointment.Jobs.Add(new Job()
{
JobName = ...,
JobDescription = ...,
});
// All primary and foreign keys will be filled as soon as you call SaveChanges
dbContext.SaveChanges();
当然,您也可以将作业所属的约会添加到上下文中
var addedJob = dbContext.Jobs.Add(new Job()
{
JobName = ...,
JobDescription = ...,
// this Job is a job of addedAppointment
Appointment = addedAppointment,
}
或者如果您已经保存了约会,则主键具有一个值:
var addedJob = dbContext.Jobs.Add(new Job()
{
JobName = ...,
JobDescription = ...,
// fill the foreign key instead
AppointmentId = addedAppointment.Id
},