Entity Framework - Ошибка присоединения объекта при создании родительского объекта - PullRequest
0 голосов
/ 08 октября 2018

Я получаю следующую ошибку

"Не удалось подключить объект типа '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; }
}

1 Ответ

0 голосов
/ 09 октября 2018

В зависимости от того, как долго ваш DbContext остается открытым, он может быть уже связан с сущностью.Например, если вы перебираете наборы Medico и два имеют один и тот же Espacialidad, первый присоединится, а второй выдает ошибку.

Перед присоединением сущности к DbContext вы всегда должны проверить, является лиобъект уже присоединен:

foreach (Especialidad especialidad in medico.Especialidad)
{
     if (!this.context.Especialidad.Local.Any(x => x == especialidad))        
         this.context.Especialidad.Attach(especialidad);
}

Редактировать: Для многих ко многим без двунаправленных ссылок.

Удалить коллекцию Medico из Especialidad

Где вы в настоящее время наносите картудокторов как-то так:

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 будетнеобходимо изменить для разрешения со стороны Доктора, т.е.

вместо:

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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...