1

엔티티 모델 :EF 코어 - 자체 참조 많은 관계로 대부분을

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

관계 모델 :

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

모델 빌더 :

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

업데이트 작가 :

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; 
     } 
    } 
나는 다음과 같은 오류 얻을 existingDocument 업데이트하려고 할 때

: 문제는 자기 참조하지

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

예외는 중복 된 'DocumentTypeRetractRelation' ** 키 **를 나타냅니다. 'existingDocument' 네비게이션 프로퍼티가 채워 졌는지 확인하십시오. 또한'DbContext'의 수명이 사용되었습니다. –

+0

그들은 있습니다. savechanges 후에 id는 savechanges 이전의 경우와 다른 동일한 엔티티의 2 배 대체됩니다. – user2963570

+0

아마도 미리로드해야하고 맹목적으로 추가하는 대신 변경 사항을 병합해야합니다. –

답변

2

을하지만, 적용 대다 같은 PK와 다른 DocumentTypeRetractRelation 객체를 생성 컬렉션을 수정 명시된 예외 메시지에서.

EF 코어 현재 올바른 방법은, (원래 값을 포함)을 existingDocumentRetractDocumentTypes가로드되어 있는지 확인 기존 또는 새로 만든 DocumentTypeRetractRelation 개체를 사용하거나하여 변경 사항을 병합하는 것입니다.

모두 제거하고 변경되지 않은 관계, 추가 처리 할 것

// 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(); 

이 다음과 같은 코드

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

를 교체합니다. DocumentTypes과 유사하게 수행 할 수 있습니다.

실제로 모델을 보면, 위의 코드는 컬렉션 (Id 문서와 조합하여 DocumentTypes 컬렉션 콘텐츠를 작성한 RetractDocumentTypeIds을 수신했기 때문에)이어야합니다. 따라서 RetractDocumentTypesDocumentTypes으로 대체하면됩니다.