엔터티 상태 작업

이 항목에서는 컨텍스트에 엔터티를 추가하고 연결하는 방법 및 SaveChanges 중에 Entity Framework에서 이러한 엔터티를 처리하는 방법을 설명합니다. Entity Framework는 컨텍스트에 연결된 동안 엔터티의 상태를 추적하지만 연결이 끊어지거나 N 계층 시나리오에서는 엔터티가 어떤 상태에 있어야 하는지 EF에 알릴 수 있습니다. 이 항목에 표시된 기술은 Code First 및 EF Designer를 사용하여 만든 모델에 동일하게 적용됩니다.

엔터티 상태 및 SaveChanges

엔터티는 EntityState 열거형에 정의된 다섯 가지 상태 중 하나일 수 있습니다. 이러한 상태는 다음과 같습니다.

  • 추가됨: 엔터티가 컨텍스트에 의해 추적되고 있지만 데이터베이스에 아직 존재하지 않음
  • 변경되지 않음: 엔터티가 컨텍스트에 의해 추적되고 데이터베이스에 있으며 해당 속성 값이 데이터베이스의 값에서 변경되지 않았습니다.
  • 수정됨: 엔터티가 컨텍스트에 의해 추적되고 데이터베이스에 있으며 해당 속성 값의 일부 또는 전부가 수정되었습니다.
  • 삭제됨: 엔터티가 컨텍스트에 의해 추적되고 데이터베이스에 있지만 다음에 SaveChanges가 호출될 때 데이터베이스에서 삭제로 표시되었습니다.
  • 분리됨: 엔터티가 컨텍스트에 의해 추적되지 않음

SaveChanges는 다른 상태의 엔터티에 대해 다른 작업을 수행합니다.

  • 변경되지 않은 엔터티는 SaveChanges에서 건드리지 않습니다. 업데이트는 변경되지 않은 상태의 엔터티에 대한 데이터베이스로 전송되지 않습니다.
  • 추가된 엔터티는 데이터베이스에 삽입된 다음 SaveChanges가 반환될 때 변경되지 않습니다.
  • 수정된 엔터티는 데이터베이스에서 업데이트된 다음 SaveChanges가 반환될 때 변경되지 않습니다.
  • 삭제된 엔터티는 데이터베이스에서 삭제된 다음 컨텍스트에서 분리됩니다.

다음 예제에서는 엔터티 또는 엔터티 그래프의 상태를 변경할 수 있는 방법을 보여 줍니다.

컨텍스트에 새 엔터티 추가

DbSet에서 Add 메서드를 호출하여 컨텍스트에 새 엔터티를 추가할 수 있습니다. 이렇게 하면 엔터티가 추가됨 상태로 전환됩니다. 즉, 다음에 SaveChanges가 호출될 때 데이터베이스에 삽입됩니다. 다음은 그 예입니다.

using (var context = new BloggingContext())
{
    var blog = new Blog { Name = "ADO.NET Blog" };
    context.Blogs.Add(blog);
    context.SaveChanges();
}

컨텍스트에 새 엔터티를 추가하는 또 다른 방법은 상태를 Add로 변경하는 것입니다. 다음은 그 예입니다.

using (var context = new BloggingContext())
{
    var blog = new Blog { Name = "ADO.NET Blog" };
    context.Entry(blog).State = EntityState.Added;
    context.SaveChanges();
}

마지막으로, 이미 추적 중인 다른 엔터티에 연결하여 컨텍스트에 새 엔터티를 추가할 수 있습니다. 이는 다른 엔터티의 컬렉션 탐색 속성에 새 엔터티를 추가하거나 다른 엔터티의 참조 탐색 속성을 설정하여 새 엔터티를 가리키는 것일 수 있습니다. 다음은 그 예입니다.

using (var context = new BloggingContext())
{
    // Add a new User by setting a reference from a tracked Blog
    var blog = context.Blogs.Find(1);
    blog.Owner = new User { UserName = "johndoe1987" };

    // Add a new Post by adding to the collection of a tracked Blog
    blog.Posts.Add(new Post { Name = "How to Add Entities" });

    context.SaveChanges();
}

추가되는 엔터티에 아직 추적되지 않은 다른 엔터티에 대한 참조가 있는 경우 이러한 새 엔터티도 컨텍스트에 추가되고 다음에 SaveChanges가 호출될 때 데이터베이스에 삽입됩니다.

컨텍스트에 기존 엔터티 연결

알고 있는 엔터티가 데이터베이스에 이미 있지만 현재 컨텍스트에서 추적되지 않는 경우 DbSet의 Attach 메서드를 사용하여 엔터티를 추적하도록 컨텍스트에 지시할 수 있습니다. 엔터티는 컨텍스트에서 변경되지 않은 상태입니다. 다음은 그 예입니다.

var existingBlog = new Blog { BlogId = 1, Name = "ADO.NET Blog" };

using (var context = new BloggingContext())
{
    context.Blogs.Attach(existingBlog);

    // Do some more work...  

    context.SaveChanges();
}

연결된 엔터티의 다른 조작을 수행하지 않고 SaveChanges를 호출하는 경우 데이터베이스는 변경되지 않습니다. 엔터티가 변경되지 않은 상태이기 때문입니다.

기존 엔터티를 컨텍스트에 연결하는 또 다른 방법은 상태를 변경되지 않은 상태로 변경하는 것입니다. 다음은 그 예입니다.

var existingBlog = new Blog { BlogId = 1, Name = "ADO.NET Blog" };

using (var context = new BloggingContext())
{
    context.Entry(existingBlog).State = EntityState.Unchanged;

    // Do some more work...  

    context.SaveChanges();
}

연결된 엔터티에 아직 추적되지 않은 다른 엔터티에 대한 참조가 있는 경우 이러한 두 예제의 경우 이러한 새 엔터티도 변경되지 않은 상태의 컨텍스트에 연결됩니다.

컨텍스트에 기존이지만 수정된 엔터티 연결

알고 있는 엔터티가 데이터베이스에 이미 있지만 변경되었을 수 있는 엔터티가 있는 경우 컨텍스트에 엔터티를 연결하고 해당 상태를 수정됨으로 설정할 수 있습니다. 다음은 그 예입니다.

var existingBlog = new Blog { BlogId = 1, Name = "ADO.NET Blog" };

using (var context = new BloggingContext())
{
    context.Entry(existingBlog).State = EntityState.Modified;

    // Do some more work...  

    context.SaveChanges();
}

상태를 수정됨으로 변경하면 엔터티의 모든 속성이 수정된 것으로 표시되고 SaveChanges가 호출될 때 모든 속성 값이 데이터베이스로 전송됩니다.

연결된 엔터티에 아직 추적되지 않은 다른 엔터티에 대한 참조가 있는 경우 이러한 새 엔터티는 변경되지 않은 상태의 컨텍스트에 연결되며 자동으로 수정되지 않습니다. 수정됨으로 표시해야 하는 엔터티가 여러 개 있는 경우 이러한 각 엔터티에 대한 상태를 개별적으로 설정해야 합니다.

추적된 엔터티의 상태 변경

항목에서 State 속성을 설정하여 이미 추적 중인 엔터티의 상태를 변경할 수 있습니다. 다음은 그 예입니다.

var existingBlog = new Blog { BlogId = 1, Name = "ADO.NET Blog" };

using (var context = new BloggingContext())
{
    context.Blogs.Attach(existingBlog);
    context.Entry(existingBlog).State = EntityState.Unchanged;

    // Do some more work...  

    context.SaveChanges();
}

이미 추적된 엔터티에 대해 추가 또는 연결 호출을 사용하여 엔터티 상태를 변경할 수도 있습니다. 예를 들어 현재 추가된 상태에 있는 엔터티에 대해 Attach를 호출하면 해당 상태가 변경되지 않음으로 변경됩니다.

패턴 삽입 또는 업데이트

일부 애플리케이션의 일반적인 패턴은 엔터티를 새로 추가(결과적으로 데이터베이스 삽입)하거나 엔터티를 기존 엔터티로 연결하고 기본 키의 값에 따라 수정(데이터베이스 업데이트 결과)로 표시하는 것입니다. 예를 들어 데이터베이스에서 생성된 정수 기본 키를 사용할 때는 키가 0인 엔터티를 새 키로, 0이 아닌 키를 가진 엔터티를 기존 키로 처리하는 것이 일반적입니다. 이 패턴은 기본 키 값의 확인에 따라 엔터티 상태를 설정하여 수행할 수 있습니다. 다음은 그 예입니다.

public void InsertOrUpdate(Blog blog)
{
    using (var context = new BloggingContext())
    {
        context.Entry(blog).State = blog.BlogId == 0 ?
                                   EntityState.Added :
                                   EntityState.Modified;

        context.SaveChanges();
    }
}

상태를 수정됨으로 변경하면 엔터티의 모든 속성이 수정된 것으로 표시되고 SaveChanges가 호출될 때 모든 속성 값이 데이터베이스로 전송됩니다.