1

Entity-Modell:EF Kern - selbst verweis viele zu viele Beziehung

public class DocumentType : CodeBase 
{ 
    [Required] 
    [MaxLength(100)] 
    public string Name { get; set; } 

    public TimeSpan? Productiontime { get; set; } 

    public bool IsDeliverable { get; set; } 

    public virtual ICollection<DocumentTypeRetractRelation> DocumentTypes { get; set; } 
    public virtual ICollection<DocumentTypeRetractRelation> RetractDocumentTypes { get; set; } 
} 

Relation Modell:

/// <summary> 
/// Relationship between document types showing which documenttypes can 
/// retracted when delivering a new document. 
/// </summary> 
[Table("DocumentTypeRetractRelation")] 
public class DocumentTypeRetractRelation 
{ 
    public int DocumentTypeId { get; set; } 
    public virtual DocumentType DocumentType { get; set; } 

    public int RetractDocumentTypeId { get; set; } 
    public virtual DocumentType RetractDocumentType { get; set; } 
} 

Modellbauer:

modelBuilder.Entity<DocumentTypeRetractRelation>().HasKey(x => new { x.DocumentTypeId, x.RetractDocumentTypeId }); 

modelBuilder.Entity<DocumentTypeRetractRelation>() 
    .HasOne(x => x.DocumentType) 
    .WithMany(x => x.DocumentTypes) 
    .HasForeignKey(x => x.DocumentTypeId); 

modelBuilder.Entity<DocumentTypeRetractRelation>() 
    .HasOne(x => x.RetractDocumentType) 
    .WithMany(x => x.RetractDocumentTypes) 
    .HasForeignKey(x => x.RetractDocumentTypeId); 

Schriftsteller Update:

public async Task<DocumentType> UpdateAsync(DocumentTypeUpdateDto documentTypeUpdateDto) 
    { 
     using (IUnitOfWork uow = UowProvider.CreateUnitOfWork<EntityContext>()) 
     { 
      var documentTypeRepo = uow.GetCustomRepository<IDocumentTypeRepository>(); 

      var existingDocument = await documentTypeRepo.GetAsync(documentTypeUpdateDto.Id); 

      if (existingDocument == null) 
       throw new EntityNotFoundException("DocumentType", existingDocument.Id); 

      foreach (var retractDocumentTypeId in documentTypeUpdateDto.RetractDocumentTypeIds) 
      { 
       existingDocument.RetractDocumentTypes.Add(new DocumentTypeRetractRelation() 
       { 
        DocumentTypeId = existingDocument.Id, 
        RetractDocumentTypeId = retractDocumentTypeId 
       }); 
      } 

      documentTypeRepo.Update(existingDocument); 

      await uow.SaveChangesAsync(); 

      return existingDocument; 
     } 
    } 

Beim Versuch, die existingDocument ich die folgende Fehlermeldung zu aktualisieren:

The instance of entity type 'DocumentTypeRetractRelation' cannot be tracked because another instance of this type with the same key is already being tracked. When adding new entities, for most key types a unique temporary key value will be created if no key is set (i.e. if the key property is assigned the default value for its type). If you are explicitly setting key values for new entities, ensure they do not collide with existing entities or temporary values generated for other new entities. When attaching existing entities, ensure that only one entity instance with a given key value is attached to the context.

+0

Die Ausnahme weist auf doppelte 'DocumentTypeRetractRelation' ** Schlüssel ** hin. Überprüfen Sie, ob die Navigationseigenschaften 'existingDocument' aufgefüllt sind. Auch die Lebensdauer des 'DbContext' wird genutzt. –

+0

Sie sind. Nach den Save Changes werden die IDs durch zweimal die selbe Entity ersetzt, was vor den Save Changes nicht der Fall ist. – user2963570

+0

Sie müssten sie wahrscheinlich im Voraus laden und dann mit Änderungen zusammenführen, anstatt blind hinzuzufügen. –

Antwort

2

Das Problem ist nicht die Selbst Referenzierung, aber die many-to-many-Sammlung Änderungen Anwendung, die als unterschiedliche DocumentTypeRetractRelation Objekte mit der gleichen PK erzeugen angegeben in der Ausnahmebedingungsnachricht.

Der richtige Weg zur Zeit in EF Core ist sicher zu machen RetractDocumentTypes der existingDocument geladen werden (die ursprünglichen Werte enthält), dann entweder durch die Änderungen fusionieren ein bestehendes oder neue DocumentTypeRetractRelation Objekte verwenden.

Ersetzen Sie den folgenden Code

foreach (var retractDocumentTypeId in documentTypeUpdateDto.RetractDocumentTypeIds) 
{ 
    existingDocument.RetractDocumentTypes.Add(new DocumentTypeRetractRelation() 
    { 
     DocumentTypeId = existingDocument.Id, 
     RetractDocumentTypeId = retractDocumentTypeId 
    }); 
} 

mit

// existingDocument.RetractDocumentTypes should be loaded (either eager or explicit) 
existingDocument.RetractDocumentTypes = (
    from retractDocumentTypeId in documentTypeUpdateDto.RetractDocumentTypeIds 
    join existingRelation in existingDocument.RetractDocumentTypes 
    on retractDocumentTypeId equals existingRelation.RetractDocumentTypeId 
    into existingRelations 
    select existingRelations.FirstOrDefault() ?? new DocumentTypeRetractRelation() 
    { 
     DocumentTypeId = existingDocument.Id, 
     RetractDocumentTypeId = retractDocumentTypeId 
    }).ToList(); 

beide hinzugefügt Dies würde behandeln, entfernt und unverändert Beziehungen. Sie können ähnlich wie DocumentTypes tun.

Eigentlich bei Ihrem Modell suchen, der obige Code für DocumentTypes Sammlung sein sollte (da Sie eine der RetractDocumentTypeIds empfangen, die mit dem Dokument Id bilden in Kombination die DocumentTypes Sammlung Inhalt). Ersetzen Sie einfach die RetractDocumentTypes durch DocumentTypes.

Verwandte Themen