[c#] 엔티티 프레임 워크에서 추적 된 엔티티를 지우는 방법

속도가 감소함에 따라 많은 엔티티에 걸쳐 실행되는 수정 코드를 실행하고 있습니다. 즉, 컨텍스트에서 추적되는 엔티티의 수가 반복 될 때마다 증가하기 때문에 시간이 오래 걸릴 수 있으므로 마지막에 변경 사항을 저장합니다. 각 반복의. 각 반복은 독립적이며 이전에로드 된 엔티티를 변경하지 않습니다.

변경 내용 추적을 끌 수 있다는 것을 알고 있지만 대량 삽입 코드가 아니기 때문에 원하지 않습니다. 엔티티를로드하고 몇 가지를 계산하고 숫자가 올바르지 않으면 새 숫자를 설정하고 업데이트 / 삭제 / 생성합니다. 일부 추가 엔티티. 각 반복에 대해 새 DbContext를 만들 수 있으며 동일한 인스턴스에서 모두 수행하는 것보다 더 빨리 실행될 수 있다는 것을 알고 있지만 더 나은 방법이있을 수 있다고 생각합니다.

그래서 질문은; 이전에 db 컨텍스트에로드 된 엔티티를 지우는 방법이 있습니까?



답변

DbContextChangeTracker를 사용하여 추가, 수정 및 삭제 된 모든 항목을 분리하는 확장 메서드에 메서드를 추가 할 수 있습니다 .

public void DetachAllEntities()
{
    var changedEntriesCopy = this.ChangeTracker.Entries()
        .Where(e => e.State == EntityState.Added ||
                    e.State == EntityState.Modified ||
                    e.State == EntityState.Deleted)
        .ToList();

    foreach (var entry in changedEntriesCopy)
        entry.State = EntityState.Detached;
}


답변

1. 가능성 : 항목 분리

dbContext.Entry(entity).State = EntityState.Detached;

항목을 분리하면 변경 추적기가 항목 추적을 중지하고 성능이 향상됩니다.

참조 : http://msdn.microsoft.com/de-de/library/system.data.entitystate(v=vs.110).aspx

2. 가능성 : 자신의 Status분야에서 작업 + 연결되지 않은 컨텍스트

연결이 끊긴 그래프를 사용할 수 있도록 엔티티의 상태를 독립적으로 제어하고 싶을 수 있습니다. 엔티티 상태에 대한 속성을 추가하고 dbContext.Entry(entity).State작업을 수행 할 때이 상태를로 변환 합니다 (저장소를 사용하여 수행).

public class Foo
{
    public EntityStatus EntityStatus { get; set; }
}

public enum EntityStatus
{
    Unmodified,
    Modified,
    Added
}

예를 보려면 다음 링크를 참조하십시오. https://www.safaribooksonline.com/library/view/programming-entity-framework/9781449331825/ch04s06.html


답변

매분 값을 업데이트하는 Windows 서비스를 실행 중이며 동일한 문제가 발생했습니다. @DavidSherrets 솔루션을 실행 해 보았지만 몇 시간 후에 속도도 느려졌습니다. 내 해결책은 모든 새로운 실행에 대해 이와 같은 새로운 컨텍스트를 만드는 것이 었습니다. 간단하지만 작동합니다.

_dbContext = new DbContext();


답변

방금이 문제에 부딪 혔고 결국 일반적인 .NET Core 종속성 주입을 사용하는 사람들을위한 더 나은 솔루션을 발견했습니다. 각 작업에 대해 범위가 지정된 DbContext를 사용할 수 있습니다. 과거 반복에서 엔티티를 확인하는 데 방해가되지 DbContext.ChangeTracker않도록 재설정 SaveChangesAsync()됩니다. 다음은 ASP.NET Core 컨트롤러 메서드의 예입니다.

    /// <summary>
    /// An endpoint that processes a batch of records.
    /// </summary>
    /// <param name="provider">The service provider to create scoped DbContexts.
    /// This is injected by DI per the FromServices attribute.</param>
    /// <param name="records">The batch of records.</param>
    public async Task<IActionResult> PostRecords(
        [FromServices] IServiceProvider provider,
        Record[] records)
    {
        // The service scope factory is used to create a scope per iteration
        var serviceScopeFactory =
            provider.GetRequiredService<IServiceScopeFactory>();

        foreach (var record in records)
        {
            // At the end of the using block, scope.Dispose() will be called,
            // release the DbContext so it can be disposed/reset
            using (var scope = serviceScopeFactory.CreateScope())
            {
                var context = scope.ServiceProvider.GetService<MainDbContext>();

                // Query and modify database records as needed

                await context.SaveChangesAsync();
            }
        }

        return Ok();
    }

ASP.NET Core 프로젝트는 일반적으로 DbContextPool을 사용하므로 DbContext 개체를 생성 / 파괴하지 않습니다. (관심이있는 경우 DbContextPool은 실제로 DbContext.ResetState()and를 호출 DbContext.Resurrect()하지만 향후 릴리스에서 변경 될 수 있으므로 코드에서 직접 호출하지 않는 것이 좋습니다.)
https://github.com/aspnet/EntityFrameworkCore/blob/v2 .2.1 / src / EFCore / Internal / DbContextPool.cs # L157


답변

EF Core 3.0에는 ChangeTracker를 재설정 할 수 있는 내부 API 가 있습니다. 프로덕션 코드에서는 사용하지 마십시오. 시나리오에 따라 테스트하는 데 도움이 될 수 있으므로 언급합니다.

using Microsoft.EntityFrameworkCore.Internal;

_context.GetDependencies().StateManager.ResetState();

코드에 대한 주석이 말했듯이;

이는 Entity Framework Core 인프라를 지원하고 공용 API와 동일한 호환성 표준이 적용되지 않는 내부 API입니다. 모든 릴리스에서 예고없이 변경 또는 제거 될 수 있습니다. 새 Entity Framework Core 릴리스로 업데이트 할 때 응용 프로그램 오류가 발생할 수 있다는 점을 염두에두고 코드에서 직접 사용해야합니다.


답변

EntityFramework Core 5.0은 추적 된 변경 사항을 지우는 새로운 방법을 도입했습니다.

_context.ChangeTracker.Clear();

https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.changetracking.changetracker.clear?view=efcore-5.0


답변

글쎄요, 제 경험상, EF 또는 어떤 조직이든 너무 많은 압력이나 복잡한 모델에서는 잘 작동하지 않는다고 생각합니다.

추적하고 싶지 않다면 정말 왜 orm을하는지 말할 것입니다.

속도가 주된 힘이라면 저장 프로 시저와 좋은 인덱싱을 능가하는 것은 없습니다.

그리고 쿼리가 항상 ID 단위 인 경우 키와 json 만있는 nosql 또는 SQL을 사용하는 것이 좋습니다. 이것은 클래스와 테이블 간의 임피던스 문제를 피할 수 있습니다.

귀하의 경우 시나리오의 경우 이러한 방식으로 객체를로드하는 것이 매우 느립니다. 실제로 귀하의 경우에는 저장 프로 시저가 네트워크를 통한 데이터 전송을 피하고 sql이 집계 등을 관리하는 데 훨씬 빠르고 최적화되어 있기 때문에 더 좋습니다.