EF Core引发异常:
System.InvalidOperationException
:'无法跟踪实体类型'Appointment
'的实例,因为已经跟踪了另一个键值为'{Id:6}'的实例。附加现有实体时,请确保仅附加一个具有给定键值的实体实例。'
即使主键= 0,也要插入模型时。
Appointment.cs
public class Appointment
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
public int Id { get; set; }
public Doctor Doctor { get; set; }
public Patient Patient { get; set; }
public DateTime DateTime { get; set; }
public Appointment()
{
}
public Appointment(Doctor doctor, Patient patient)
{
this.Doctor = doctor;
this.Patient = patient;
this.DateTime = DateTime.Now;
}
public Appointment(Doctor doctor, Patient patient, DateTime dateTime)
{
this.Doctor = doctor;
this.Patient = patient;
this.DateTime = dateTime;
}
}
我如何创建约会实例:
internal async Task AddAppointmentAsync(int doctorId, int patientId, DateTime dateTime)
{
Doctor doctor = null;
Patient patient = null;
//Retrieve doctor from the db
using (var doctorController = new DoctorController())
await Task.Run(() => doctor = doctorController.GetDoctor(doctorId));
if (doctor == null)
throw new KeyNotFoundException("Doctor with the specified id doesn't exist.");
//Retrieve patient from the db
using (var patientController = new PatientController())
await Task.Run(() => patient = patientController.GetPatient(patientId));
if (patient == null)
throw new KeyNotFoundException("Patient with the specified id doesn't exist.");
//Create and insert appointment into the db
Appointment appointment = new Appointment(doctor, patient, dateTime);
using (_controller = new AppointmentController())
await Task.Run(() => _controller.AddAppointment(appointment));
}
添加约会方式
public void AddAppointment(Appointment appointment)
{
if (appointment == null) throw new ArgumentNullException(nameof(appointment));
if (appointment.Doctor == null) throw new ArgumentNullException(nameof(appointment.Doctor));
if (appointment.Patient == null) throw new ArgumentNullException(nameof(appointment.Patient));
Doctor doctor = appointment.Doctor;
Patient patient = appointment.Patient;
appointment.Doctor = null;
appointment.Patient = null;
this._context.Appointments.Add(appointment);
appointment.Doctor = doctor;
appointment.Patient = patient;
this._context.SaveChanges(); //Exception is thrown here
}
我的环境:
public class HospitalContext : DbContext
{
private const string _connectionString = "Server=(localdb)\\mssqllocaldb;Database=ClientDb;Trusted_Connection=True;";
public DbSet<Doctor> Doctors { get; private set; }
public DbSet<Patient> Patients { get; private set; }
public DbSet<Appointment> Appointments { get; private set; }
public DbSet<MedicalRecord> MedicalRecords { get; private set; }
public HospitalContext()
: base()
{
}
public HospitalContext(DbContextOptions<HospitalContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Doctor>()
.HasMany(d => d.Appointments)
.WithOne(a => a.Doctor)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<Doctor>()
.HasMany(w => w.WorkDays)
.WithOne(a => a.Doctor)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<Patient>()
.HasMany(p => p.Appointments)
.WithOne(p => p.Patient)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<Patient>()
.HasMany(p => p.MedicalRecords)
.WithOne(m => m.Patient)
.OnDelete(DeleteBehavior.Cascade);
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer(_connectionString);
optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
optionsBuilder.EnableSensitiveDataLogging();
}
}
}
我要传递给该方法的内容:
我的约会表中已经有什么:
更新
看来我的表不能包含具有相同DoctorId
和PatientId
外键的多个条目。
例如:尝试添加DoctorId = 3,PatientId = 1的条目时引发异常:
答案 0 :(得分:1)
如果您尝试插入的实体在数据库中已经有一个实体的ID, 那么很可能是数据库中已经存在的实体。
也许您会做类似的事情:
var item = YourCollection.First();
item.ID = 0;
item.DateTime = DateTime.Now
YourCollection.Add(item);
这行不通,并且会产生您的行为。您必须使用new Appointment()
如果您插入两次,也会发生同样的情况
YourCollection.Add(item);
YourCollection.Add(item);
这不是您的情况,因为您已分配了现有商品的ID。
按ID跟踪只是实体框架的一部分,但它也通过引用跟踪实体。
答案 1 :(得分:0)
在将实体的State
分配到Added
之前,将其添加到上下文中可以解决此问题。
添加约会方式
public void AddAppointment(Appointment appointment)
{
if (appointment == null) throw new ArgumentNullException(nameof(appointment));
if (appointment.Doctor == null) throw new ArgumentNullException(nameof(appointment.Doctor));
if (appointment.Patient == null) throw new ArgumentNullException(nameof(appointment.Patient));
this._context.Entry(appointment).State = EntityState.Added;
this._context.Appointments.Add(appointment);
this._context.SaveChanges();
}