LINQ to Entities에서 대량 삭제


82

LINQ 또는 LINQ-to-Entities에서 지정된 쿼리와 일치하는 여러 개체를 대량으로 삭제할 수있는 방법이 있습니까? 내가 찾을 수있는 유일한 참조는 구식이며 제거하려는 모든 개체를 반복하고 수동으로 삭제하는 것은 어리석은 것 같습니다.

답변:



53

얼마 전에 Entity Framework에서 대량 업데이트 (하나의 명령 사용)를 다루는 4 부로 구성된 블로그 시리즈 ( 1 부 , 2 부 , 3 부4 부 )를 작성했습니다.

이 시리즈의 초점은 업데이트 였지만 삭제를 위해 관련된 원칙을 확실히 사용할 수 있습니다.

따라서 다음과 같이 작성할 수 있어야합니다.

var query = from c in ctx.Customers
            where c.SalesPerson.Email == "..."
            select c;

query.Delete();

해야 할 일은 Delete () 확장 메서드를 구현하는 것뿐입니다. 방법에 대한 힌트는 포스트 시리즈를 참조하십시오.

도움이 되었기를 바랍니다


17
누군가 가지고 있다면 여기에 대한 코드 샘플이 있으면 좋을 것입니다!
jocull

1
여러 확장 방법 (일괄 삭제 포함)은 여기에서 찾을 수 있습니다. github.com/loresoft/EntityFramework.Extended
Soliah

1
주의 github.com/loresoft/EntityFramework.Extended는 당신이 EF5 설치 요구하지 않고 것, 당신이 Nuget 패키지 관리자 콘솔을 설치하는 데 사용하는 경우, EF5에 종속
폴 자 흐라

1
실제로 도움이되지 않습니다. 프로덕션 코드에서 내 자신을 구현하는 방법을 "추측"하지 않고 삭제 명령의 작동 예제를보고 싶습니다. -1
nuzzolilo 2013

27
그래서 질문에 대한 답은 청중에게 구체적인 답변을 제시하는 대신 4 개의 블로그 게시물로 리디렉션하는 것입니다.
DeepSpace101 2013-04-13

41
    using (var context = new DatabaseEntities())
    {
        // delete existing records
        context.ExecuteStoreCommand("DELETE FROM YOURTABLE WHERE CustomerID = {0}", customerId);
    }

3
+1-EF를 사용하여 SQL 코드를 실행하는 방법에 대한 코드 예제를 보니 반갑습니다
Carlos P

2
저장 프로 시저를 만드는 것보다 이것이 아마도 이것을 수행하는 유일한 방법이라는 것을 알고 있지만 이것은 속임수 =)처럼 느껴집니다. 이제 내가 이것을 사용하고 있기 때문에 복잡한 왼쪽 조인 및 그룹
바이

+! ... DB를 사용하면 원하는 도구가 드라이버라는 것을 알 수 있습니다. EF는 또 다른 망치입니다.
gbjbaanb

2
약간의 단점 : 이제 개발 환경에서 연결이 끊어진 데이터베이스 명령이 있습니다. 강력한 형식 이 아니므 로이 SQL의 열에 대한 데이터베이스 변경 사항 은 Visual Studio에서 강조 표시되지 않습니다.
Ian

7

내가 여기서보고있는 답변은 Linq to Sql입니다.

DeleteAllOnSubmit은 System.Data.Linq의 일부이며 Linq to Sql 인 ITable입니다.

Entity Framework에서는이 작업을 수행 할 수 없습니다.

아직 해결책이 없지만 할 때 다시 게시하겠습니다.


5

EF6를 사용하고 삭제를 위해 행 SQL 쿼리를 실행하려는 경우 :

using (var context = new DatabaseEntities())
{
    // delete existing records
    context.Database.ExecuteSqlCommand("DELETE FROM YOURTABLE WHERE CustomerID = @id", idParameter);
}

1
이것은 EF 5에서 나를 위해 일했지만 매개 변수로 @ p0을 사용해야했습니다. 좋은 점은 생성 된 SQL에서 형식 안전 매개 변수 검사를 제공한다는 것입니다. 따라서 EF5에서는 다음과 같이 작동합니다. context.Database.ExecuteSqlCommand ( "DELETE FROM YOURTABLE WHERE CustomerID = @ p0", idParameter); \ @ p1 for next param, etc ...
Nathan Prather 2014

3

RemoveRange는 EF6에서 도입되었으며 개체 목록을 제거 할 수 있습니다. 아주 쉽습니다.

var origins= (from po in db.PermitOrigins where po.PermitID == thisPermit.PermitID select po).ToList();
db.PermitOrigins.RemoveRange(origins);
db.SaveChanges();

1
이 코드 스 니펫은 질문을 해결할 수 있지만 설명을 포함하면 게시물의 품질을 향상시키는 데 큰 도움이됩니다. 미래에 독자를 위해 질문에 답하고 있으며 해당 사용자는 코드 제안 이유를 모를 수 있습니다.
DimaSan

2

쿼리의 모든 레코드를 삭제하는 데이터 컨텍스트 의 DeleteAllOnSubmit 메서드를 알고 있습니다. 많은 객체가 삭제되고 있으므로 몇 가지 최적화가 있어야합니다. 그래도 잘 모르겠습니다.


3
실제로 수행중인 최적화가 없습니다. 생성 된 SQL은 쿼리와 일치하는 모든 개체를 열거 한 다음 수동으로 반복하여 삭제합니다. 물론, 반복은 코드가 아닌 DB에서 발생하지만, 그 내용을 삭제하기 위해 결과 집합을 불필요하게 구축하고 있습니다. 결과 세트가 없으며 테이블을 한 번만 다룹니다.
Benjamin Pollack

2

얼마나 효율적인지 잘 모르겠지만 다음과 같이 시도해 볼 수 있습니다.

// deletes all "People" with the name "Joe"
var mypeople = from p in myDataContext.People
               where p.Name == "Joe";
               select p;
myDataContext.People.DeleteAllOnSubmit(mypeople);
myDataContext.SubmitChanges();

1
여전히 쿼리와 일치하는 모든 요소를 ​​반복합니다. 코드가 아닌 DB에서 그렇게 할뿐입니다. 더 효율적이지만 여전히 이상적인 솔루션과는 거리가 멀습니다.
Benjamin Pollack

3
내가 생각할 수있는 유일한 다른 방법은 myDataContext.ExecuteCommand ( "DELETE ...");를 수행하는 것입니다. 이상적인 것과는 거리가 멀지 만 작동합니다.
Scott Anderson

1

당신은 삭제를 수행하고 LINQ에서 호출하는 저장된 proc을 작성할 수 있습니다. 집합 기반 삭제는 전체적으로 더 빠를 수 있지만 너무 많은 레코드에 영향을 미치는 경우 잠금 문제가 발생할 수 있으며 레코드 집합을 통해 반복되는 하이브리드가 필요할 수 있습니다 (한 번에 2000 개 정도, 크기는 데이터베이스 디자인에 따라 다르지만 2000은 집합 기반 delte가 너무 오래 걸리는 경우 테이블의 다른 사용에 영향을 미치는 경우 시작 위치) 삭제를 수행하십시오.


1

Entity Framework를 통해 데이터를 삭제하려면 DeleteObject 메서드를 사용해야합니다. 삭제할 엔터티 클래스의 EntityCollection 또는 파생 된 ObjectContext에서이 메서드를 호출 할 수 있습니다. 다음은 간단한 예입니다.

NorthwindEntities db = new NorthwindEntities();

IEnumerable<Order_Detail> ods = from o in db.Order_Details
                                where o.OrderID == 12345                                    
                                select o;

foreach (Order_Detail od in ods) 
    db.Order_Details.DeleteObject(od);

db.SaveChanges();

그래도 "대량 삭제"는 아닙니다.
nuzzolilo 2013

1

이 예에서는 삭제할 레코드를 가져 와서 하나씩 결과 세트에 첨부 한 다음 제거하도록 요청합니다. 그런 다음 1 개의 저장 변경 사항이 있습니다.

    using (BillingDB db = new BillingDB())
    {
      var recordsToDelete = (from i in db.sales_order_item
                  where i.sales_order_id == shoppingCartId
                  select i).ToList<sales_order_item>();

      if(recordsToDelete.Count > 0)
      {
        foreach (var deleteSalesOrderItem in recordsToDelete)
        {                  
            db.sales_order_item.Attach(deleteSalesOrderItem);
            db.sales_order_item.Remove(deleteSalesOrderItem);                  
        }
        db.SaveChanges();
      } 
    }

1
 context.Entity.Where(p => p.col== id)
               .ToList().ForEach(p => db.Entity.DeleteObject(p));

EF를 사용하여 DB에서 레코드를 삭제하는 가장 빠른 방법입니다.


0

나는 다음과 같이 할 것이다.

var recordsToDelete = (from c in db.Candidates_T where c.MyField == null select c).ToList<Candidates_T>();
if(recordsToDelete.Count > 0)
{
    foreach(var record in recordsToDelete)
    {
        db.Candidate_T.DeleteObject(record);
        db.SaveChanges();
    }
}   

Entity Framework는 엔터티와 함께 ​​작동하고 대부분의 경우 개체 컬렉션을 의미하므로 루프없이 수행 할 수있는 방법이 없다고 생각합니다.


당신이 한 일도 공유 할 수 있습니다. 감사.
G Jeny Ramirez 2015

@G Jeny Ramirez 내 솔루션을 추가했습니다.
Demodave

2
@GJennyRamirez 또한 귀하의 예제에서 saveChanges를 여러 번 저장하고 있습니다. foreach 루프를 벗어나 한 번 실행할 수 있다고 생각합니다.
Demodave
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.