簡體   English   中英

實體框架-創建父實體時附加實體錯誤

[英]Entity Framework - Attach entity Error when creating Parent Entity

我收到以下錯誤

“附加類型為'Datos.Medico'的實體失敗,因為相同類型的另一個實體已經具有相同的主鍵值。使用'附加'方法或將實體的狀態設置為'未更改'或'如果圖表中的任何實體具有沖突的鍵值,則為“已修改”。這可能是因為某些實體是新實體,尚未收到數據庫生成的鍵值。在這種情況下,請使用“添加”方法或“已添加”實體狀態進行跟蹤圖形,然后根據需要將非新實體的狀態設置為“未更改”或“已修改”。

當我嘗試將實體附加到上下文時,將發生以下錯誤:

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>

提前致謝。

更新

我根據要求包括實體定義:

    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; }

Especialidad:

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; }
}

根據您的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插入錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM