엔티티 프레임 워크를 사용하여 ID로 객체를 삭제하는 방법


105

아래와 같이 엔티티 프레임 워크로 삭제하기 전에 객체를 검색해야하는 것 같습니다.

var customer = context.Customers.First(c => c.Id == 1);

context.DeleteObject(customer);

context.Savechanges();

그래서 저는 데이터베이스를 두 번 쳐야합니다. 더 쉬운 방법이 있습니까?


j.mp/f0x0Bh 가 답입니다. 이것은 훌륭하고 일반적인 방법입니다
BritishDeveloper 2011 년

답변:


93

Entity Framework 6에서 삭제 작업은 Remove. 다음은 예입니다.

Customer customer = new Customer () { Id = id };
context.Customers.Attach(customer);
context.Customers.Remove(customer);
context.SaveChanges();

16
Attach? 왜 그냥 RemoveSaveChanges?
runeks

3
그렇지 않으면 제거하는 동안 오류가 발생하므로 컨텍스트에서 엔터티를 연결해야합니다. EF는이 컨텍스트에서만 엔티티를 제거 할 수 있습니다.
Pierre-Luc

3
@runeks 설명서에 따르면 제거 작업을 수행하려면 먼저 엔터티가 컨텍스트에 있어야합니다. 여기 docs.microsoft.com/en-us/dotnet/api/…를
dwkd

1
나는 첨부 파일을 사용하지 않았고 잘 작동합니다
ILIAS M. DOLAPO

58

강력하게 입력해야하는 작은 변경 사항이있는 @Nix와 동일합니다.

쿼리하지 않으려면 엔터티를 만든 다음 삭제하면됩니다.

                Customer customer = new Customer () { Id = id };
                context.Customers.Attach(customer);
                context.Customers.DeleteObject(customer);
                context.SaveChanges();

7
개체가 누락 된 경우 예외가 발생하므로 완벽하지 않습니다. "DbUpdateConcurrencyException : 저장소 업데이트, 삽입 또는 삭제 문이 예기치 않은 행 수 (0)에 영향을 미쳤습니다." DELETE 문처럼 이것을 무시하고 싶습니다.
Dunc 2015 년

죄송합니다. 이로 인해 항상 필요하지 않고 예상되는 유효성 검사가 발생합니다!
Hamed Zakery Miab

32

여기에 비슷한 질문이 있습니다 .

Entity Framework에는 EntityFramework-Plus (확장 라이브러리)가 있습니다.
NuGet에서 사용할 수 있습니다. 그런 다음 다음과 같이 작성할 수 있습니다.

// DELETE all users which has been inactive for 2 years
ctx.Users.Where(x => x.LastLoginDate < DateTime.Now.AddYears(-2))
     .Delete();

대량 삭제에도 유용합니다.


36
이것은 지금까지 핵심 EF 라이브러리의 일부가 아니라는 이유를 무시합니다.
nathanchere

1
@FerretallicA-동의했습니다.
acarlon

2
이 메서드는 더 이상 사용되지 않습니다. context.Users.Where (user => user.Id == id) .Delete ();
Manuel

"A FROM 절은 현재 DELETE 문에서 지원되지 않습니다."오류로 인해 Azure SQL DataWarehouse에서 작동하지 않습니다. 그러나 Jonik의 대답 과 같은 원시 SQL이 작동합니다.
마이클 Freidgeim

1
context.SaveChanges ()가 필요합니까?
Tomas Kubes 2018

23

쿼리하지 않으려면 항목을 만든 다음 삭제하면됩니다.

Customer customer  = new Customer() {  Id = 1   } ; 
context.AttachTo("Customers", customer);
context.DeleteObject(customer);
context.Savechanges();

6

내 프로젝트 중 하나에서 다음 코드를 사용하고 있습니다.

    using (var _context = new DBContext(new DbContextOptions<DBContext>()))
    {
        try
        {
            _context.MyItems.Remove(new MyItem() { MyItemId = id });
            await _context.SaveChangesAsync();
        }
        catch (Exception ex)
        {
            if (!_context.MyItems.Any(i => i.MyItemId == id))
            {
                return NotFound();
            }
            else
            {
                throw ex;
            }
        }
    }

이렇게하면 지정된 ID를 가진 항목을 제거하려고 할 때 예외가 발생하는 경우에만 데이터베이스를 두 번 쿼리합니다. 그런 다음 항목을 찾을 수 없으면 의미있는 메시지를 반환합니다. 그렇지 않으면 예외를 다시 던집니다 (다른 예외 유형에 대해 다른 catch 블록을 사용하여 사례에 더 적합하게 처리하고 if 블록 등을 사용하여 더 많은 사용자 지정 검사를 추가 할 수 있습니다).

[Entity Framework Core가있는 MVC .Net Core / .Net Core 프로젝트에서이 코드를 사용하고 있습니다.]


2

원시 SQL 쿼리는 내가 생각하는 가장 빠른 방법입니다.

public void DeleteCustomer(int id)
{
   using (var context = new Context())
   {
      const string query = "DELETE FROM [dbo].[Customers] WHERE [id]={0}";
      var rows = context.Database.ExecuteSqlCommand(query,id);
      // rows >= 1 - count of deleted rows,
      // rows = 0 - nothing to delete.
   }
}

19
이것은 EF에서 강력한 형식의 개체 기능을 사용하는 목적을 무효화합니다.
LawMan 2015 년

4
이것은 EF 신원 현금을 손상시킵니다. 이 후에도 EF는 삭제 된 엔터티를 반환합니다.
epox

1
다른 솔루션이 아닌 경우 Azure SQL DataWarehouse와 함께 작동합니다.
마이클 Freidgeim

1
이 작업을 수행하는 경우 ORM을 사용하지 않는 것이 좋습니다. 이것이 EF 캐시를 손상시킬 것이라고 생각합니다.
Storm Muller

이 스타일은 SQL Injection 공격에 취약합니다. 이 특정 예제에서는 변수가 정수이기 때문에 보호되지만 문자열 변수와 함께이 패턴을 사용하지 마십시오.
thelem

2

dwkd의 대답은이 예외를 보았을 때를 제외하고는 Entity Framework 코어에서 주로 저에게 효과적이었습니다.

InvalidOperationException : { 'Id'}에 대해 동일한 키 값을 가진 다른 인스턴스가 이미 추적 중이므로 항목 유형 'Customer'의 인스턴스를 추적 할 수 없습니다. 기존 엔터티를 연결할 때 지정된 키 값이있는 엔터티 인스턴스가 하나만 연결되었는지 확인합니다. 충돌하는 키 값을 보려면 'DbContextOptionsBuilder.EnableSensitiveDataLogging'을 사용하는 것이 좋습니다.

예외를 피하기 위해 코드를 업데이트했습니다.

Customer customer = context.Customers.Local.First(c => c.Id == id);
if (customer == null) {
    customer = new Customer () { Id = id };
    context.Customers.Attach(customer);
}
context.Customers.Remove(customer);
context.SaveChanges();

1

더 작은 버전 (이전 버전과 비교시) :

var customer = context.Find(id);
context.Delete(customer);
context.SaveChanges();

이 코드 스 니펫에 대한 컨텍스트와 지난 10 년 동안 남긴 다른 답변보다 더 나은 점에 대한 설명을 제공하십시오.
miken32

1

이 답변은 실제로 ASP.NET MVC 5 Fundamentals라는 Scott Allen의 과정에서 가져온 것입니다. 나는 이미 여기에있는 어떤 대답보다 약간 더 간단하고 직관적이라고 생각하기 때문에 공유하겠다고 생각했습니다. 또한 Scott Allen 및 내가 수행 한 다른 교육에 따르면 find 메서드는 이미 검색된 경우 캐싱을 사용할 수있는 데이터베이스에서 리소스를 검색하는 최적화 된 방법입니다. 이 코드에서 컬렉션은 개체의 DBSet을 나타냅니다. 개체는 모든 일반 개체 유형이 될 수 있습니다.

        var object = context.collection.Find(id);  
        context.collection.Remove(object);
        context.SaveChanges();
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.