我收到以下错误
“附加类型为'Datos.Medico'的实体失败,因为相同类型的另一个实体已经具有相同的主键值。使用'Attach'方法或将实体的状态设置为'Unchanged'时,可能会发生这种情况。 '或'Modified'(如果图形中的任何实体具有冲突的键值),这可能是因为某些实体是新的并且尚未接收到数据库生成的键值。在这种情况下,请使用'Add'方法或'Added'实体状态以跟踪图形,然后根据需要将非新实体的状态设置为“未更改”或“已修改”。”
当我尝试将实体附加到上下文时,发生错误,如下所示:
public override void Alta(Medico medico)
{
foreach (Especialidad especialidad in medico.Especialidad)
{
this.context.Especialidad.Attach(especialidad);
}
base.Alta(medico);
}
获取Especialidad
实体是为了跟踪,因为它用于填充组合:
public List<Especialidad> ObtenerEspecialidades()
{
var especialidades = context.Especialidad.AsNoTracking();
/*
var especialidades = from unaEspecialidad in context.Especialidad
select unaEspecialidad;
*/
return especialidades.ToList();
}
然后从组合中取出并添加到Medico
实体中,该实体包含一个List<Especialidad>
。
谢谢。
更新
我根据要求包含了Entities定义:
public Medico()
{
this.Agenda = new HashSet<Agenda>();
this.Historia_Clinica_Elemento = new HashSet<HistoriaClinicaElemento>();
this.Turno = new HashSet<Turno>();
this.Especialidad = new HashSet<Especialidad>();
this.Espera_Atencion = new HashSet<EsperaAtencion>();
}
public int ID { get; set; }
public string Nombre { get; set; }
public string Apellido { get; set; }
public Nullable<int> Matricula { get; set; }
public Nullable<int> TipoDocumento { get; set; }
public Nullable<long> Numero_Documento { get; set; }
public Nullable<System.DateTime> Fecha_Nacimiento { get; set; }
public Nullable<int> Direccion { get; set; }
public string Usuario { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Agenda> Agenda { get; set; }
public virtual Direccion Direccion1 { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<HistoriaClinicaElemento> Historia_Clinica_Elemento { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Turno> Turno { get; set; }
public virtual TipoDocumento Tipo_Documento { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Especialidad> Especialidad { get; set; }
public virtual Usuario Usuario1 { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<EsperaAtencion> Espera_Atencion { get; set; }
特殊:
public partial class Especialidad
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Especialidad()
{
this.Medico = new HashSet<Medico>();
}
public int ID { get; set; }
public string Nombre { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Medico> Medico { get; set; }
}
答案 0 :(得分:0)
取决于您的DbContext保持打开状态的时间,它可以已经与实体关联。例如,如果您要遍历一组Medico,并且两个具有相同的Espacialidad,则第一个将附加,而第二个将引发错误。
在将实体附加到DbContext之前,应始终检查该实体是否已附加:
foreach (Especialidad especialidad in medico.Especialidad)
{
if (!this.context.Especialidad.Local.Any(x => x == especialidad))
this.context.Especialidad.Attach(especialidad);
}
编辑:适用于许多没有双向引用的情况。
从Especialidad移除Medico系列
您目前在哪里将医生映射为以下位置:
HasMany(x => x.Especialidad)
.WithMany(x => x.Medico)
.Map(x =>
{
x.ToTable("Medico_Especialidad");
x.MapLeftKey("MedicoID");
x.MapRightKey("EspecialidadID");
});
...这将变为:
HasMany(x => x.Especialidad)
.WithMany() // Note the empty return reference.
.Map(x =>
{
x.ToTable("Medico_Especialidad");
x.MapLeftKey("MedicoID");
x.MapRightKey("EspecialidadID");
});
您可能需要使用Especialidad的专业来获取医生的任何代码.Medico将需要更改以从Doctor一方解决,即
代替:
var medicos = context.Especialidad.Find(especialidadID).Medico
看起来像:
var medicos = context.Medico.Where(x => x.Especialidad.Any(e => e.ID == especialidadID)).ToList();
当涉及多对多或多对一关系时,为使代码更简单并避免引用混淆,通常建议避免双向引用,除非绝对需要它们。双向引用带来的部分麻烦是,当A引用B且B引用A时,您需要确保上下文能够在两边解析出完全相同的A和B。将实体分离并重新附加到上下文时,这将导致关联错误或重复的PK插入错误。