Entity Framework에서 여러 행을 삭제하는 방법 (foreach 제외)


305

Entity Framework를 사용하여 테이블에서 여러 항목을 삭제하고 있습니다. 외래 키 / 부모 개체가 없으므로 OnDeleteCascade 로이를 처리 할 수 ​​없습니다.

지금 나는 이것을하고있다 :

var widgets = context.Widgets
    .Where(w => w.WidgetId == widgetId);

foreach (Widget widget in widgets)
{
    context.Widgets.DeleteObject(widget);
}
context.SaveChanges();

그것은 효과가 있지만 foreach는 나를 버그로 만듭니다. EF4를 사용하고 있지만 SQL을 실행하고 싶지 않습니다. 나는 단지 내가 빠진 것이 없는지 확인하고 싶습니다-이것이 얻는 것만 큼 좋습니다. 확장 방법이나 도우미로 추상화 할 수 있지만 어딘가에서 foreach를 수행 할 것입니다.


1
허용 된 답변을 다시 방문 할 수 있습니다.
Eric J.

1
성능을 유지하려면 여기에서 내 대답을 확인하고 싶을 수도 있습니다. stackoverflow.com/a/35033286/274589
Adi

답변:


49

루프에서 DeleteObject를 직접 호출하여 SQL을 실행하지 않으려면 오늘 최선을 다하십시오.

그러나 여기에 설명 된 접근 방식을 사용하여 SQL을 실행하고 확장 방법을 통해 완전히 범용으로 만들 수 있습니다 .

그 대답은 3.5였습니다. 4.0의 경우 아마도 StoreConnection으로 드롭 다운하는 대신 새로운 ExecuteStoreCommand API를 사용합니다.


ExecuteStoreCommand는 올바른 방법이 아닙니다 .DeleteAllSubmit은 linq에서 sql로 작동하지만 엔티티 프레임 워크에서는 작동하지 않습니다. 엔티티 프레임 워크에서 동일한 옵션을 원합니다.
Hiral

653

EntityFramework 6을 사용하면이 작업을보다 쉽게 ​​수행 할 수 있습니다 .RemoveRange().

예:

db.People.RemoveRange(db.People.Where(x => x.State == "CA"));
db.SaveChanges();

31
그것이 우리에게 필요한 것입니다 ... 충분히 넓은 범위에서 사용할 때를 제외하고는 메모리 부족 예외가 발생합니다! RemoveRange의 요점은 처리를 데이터베이스로 전달하는 것이 아니라고 생각했습니다.
Samer Adra

삭제 된 상태를 모든 엔티티로 설정하는 것보다 WAAAYYYY가 빠릅니다!
Jerther

54
확실히이 대답은 쉽지만 성능면에서는 좋지 않습니다. 왜? 이 exatly doet은 foreach 루프에서 삭제하는 것과 동일합니다. 먼저 모든 행을 가져온 다음 하나씩 삭제합니다. "감지 변경은 엔티티를 삭제하기 전에 한 번 호출되고 다시 호출되지 않습니다"rest 동일하지만 도구를 사용하여 SQL 생성을보십시오.
Anshul Nigam

6
충분히 큰 범위의 경우 .Take (10000)와 같은 것을 시도하고 RemoveRange (...). Count () == 0까지 반복합니다.
Eric J.

20
문제는 RemoveRange 입력 매개 변수가 IEnumerable이므로 삭제를 수행하면 모든 엔터티를 열거하고 엔터티 당 1 DELETE 쿼리를 실행한다는 것입니다.
bubi

74

이것이 얻는 것만 큼 좋습니다. 확장 방법이나 도우미로 추상화 할 수 있지만 어딘가에서 foreach를 수행 할 것입니다.

네, 두 개의 라이너로 만들 수 있다는 점을 제외하고는 :

context.Widgets.Where(w => w.WidgetId == widgetId)
               .ToList().ForEach(context.Widgets.DeleteObject);
context.SaveChanges();

76
목적을 무효화하는 ToList ()를 수행하고 있습니다. 원래 솔루션과 다른 점은 무엇입니까?
lahsrah

3
컨텍스트 객체에 Remove 메소드 만 있기 때문에 문제가 있습니다.
Pnct

2
이것은 백만 행 (또는 수백 개)이 예상 될 때 적합한 솔루션이 아닙니다. 그러나 우리가 확실히 알고 있다면 몇 줄만있을 것입니다.이 솔루션은 깔끔하고 완벽하게 작동합니다. 그렇습니다 .DB로 몇 번의 왕복 여행이 필요하지만 SQL 호출과 관련하여 손실 된 추상화가 이점을 능가합니다.
Yogster

이름에서 알 수 있듯이 Entity Framework는 엔터티 수준의 데이터와 가장 잘 작동합니다. 대량의 데이터 작업은 오래된 저장 프로 시저가 가장 잘 처리합니다. 성능면에서 그들은 최고의 옵션이며 루프가 필요한 모든 EF 로직을 능가합니다.
Paceman

72
using (var context = new DatabaseEntities())
{
    context.ExecuteStoreCommand("DELETE FROM YOURTABLE WHERE CustomerID = {0}", customerId);
}

그러나 ID 목록으로 어떻게 할 수 있습니까? 이 솔루션은 "목록"을 잘 처리하지 못합니다.
JesseNewman19

11
@ JesseNewman19 ID 목록이 이미있는 경우을 사용 WHERE IN ({0})하고 두 번째 인수는이어야합니다 String.Join(",", idList).
Langdon

@Langdon은 작동하지 않습니다. WHERE IN ( "1, 2, 3")과 같이 sql에 명령을 전송하기 때문입니다. 그런 다음 정수 목록 대신 문자열을 전달했기 때문에 데이터베이스에서 오류가 발생합니다.
JesseNewman19'1 /

LINQ를 사용하여 이와 같은 문장을 생성하고 싶습니다. 내가 찾은 가장 가까운 것은 lib였습니다. EntityFramework.Extended
Jaider

당신이 사용하는 경우 String.Join, 당신은 사용해야 string.Format하고 명령에 이미 형성 SQL 문자열을 전달합니다. 목록에 정수만 있으면 주입 공격의 위험이 없습니다. 이 질문을 확인하십시오 : 어떻게 배열을 execute store 명령에 전달할 수 있습니까?
앤드류

50

나는 그것이 늦었다는 것을 알고 있지만 누군가가 간단한 해결책이 필요한 경우 멋진 점은 where 절을 추가 할 수 있다는 것입니다.

public static void DeleteWhere<T>(this DbContext db, Expression<Func<T, bool>> filter) where T : class
{
    string selectSql = db.Set<T>().Where(filter).ToString();
    string fromWhere = selectSql.Substring(selectSql.IndexOf("FROM"));
    string deleteSql = "DELETE [Extent1] " + fromWhere;
    db.Database.ExecuteSqlCommand(deleteSql);
}

참고 : MSSQL2008로 방금 테스트했습니다.

최신 정보:

EF가 parameters로 sql 문을 생성 할 때 위의 솔루션이 작동하지 않으므로 EF5에 대한 업데이트가 있습니다 .

public static void DeleteWhere<T>(this DbContext db, Expression<Func<T, bool>> filter) where T : class
{
    var query = db.Set<T>().Where(filter);

    string selectSql = query.ToString();
    string deleteSql = "DELETE [Extent1] " + selectSql.Substring(selectSql.IndexOf("FROM"));

    var internalQuery = query.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Where(field => field.Name == "_internalQuery").Select(field => field.GetValue(query)).First();
    var objectQuery = internalQuery.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Where(field => field.Name == "_objectQuery").Select(field => field.GetValue(internalQuery)).First() as ObjectQuery;
    var parameters = objectQuery.Parameters.Select(p => new SqlParameter(p.Name, p.Value)).ToArray();

    db.Database.ExecuteSqlCommand(deleteSql, parameters);
}

약간의 반사가 필요하지만 잘 작동합니다.


DbContext 란 무엇입니까? 자동 생성 된 엔티티 프레임 워크 컨텍스트를 가정합니다. Set <T>라는 메서드가 없습니다.
Stealth Rabbi

@Stealth : 예, EF 데이터 컨텍스트이므로 코드 우선을 사용하지만 자동 생성 컨텍스트는 동일해야합니다. 잘못 입력 한 문장에 대해 죄송합니다. Set <T> () (내 회사는 인터넷 액세스를 제한하여 코드를 붙여 넣을 수 없었으며 직접 입력해야했습니다 ...), 코드 업데이트 :)
Thanh Nguyen

3
이것은 실제로 질문에 대답하는 유일한 대답입니다! 다른 모든 답변은 한 번에 하나씩 개별 항목을 삭제합니다.
Rocklan

이것은 가장 정답 인 것 같습니다. 매우 일반적인 방식으로 삭제가 가능하며 작업을 C #이 아닌 데이터베이스로 올바르게 오프로드합니다.
JesseNewman19

1
기술이 부족한 모든 프로그래머를 위해, 몇 분의 시간을 절약 할 수 있었기 때문에이 우수하고 일반적인 솔루션을 구현하는 방법에 대해 좀 더 자세히 설명하고 싶었습니다! 다음 코멘트에 계속 ...
jdnew18

30

EF5를 사용하는 사람은 다음 확장 라이브러리를 사용할 수 있습니다. https://github.com/loresoft/EntityFramework.Extended

context.Widgets.Delete(w => w.WidgetId == widgetId);

3
내 상황에서는 사용할 수없는 큰 테이블에 성능 문제가 있습니다.
Tomas

@Tomas 어떤 종류의 성능이 발표 되었습니까? 문제가 얼마나 심각했고 테이블이 얼마나 컸습니까? 다른 사람이 그것을 확인할 수 있습니까?
Anestis Kivranoglou

그것은 대안에 비해 정말 빠릅니다
Jaider

Delete()EF6의 엔티티에서 기능을 볼 수 없습니다 .
dotNET

context.Widgets.Where(w => w.WidgetId == widgetId).Delete();확장 된
Peter Kerr

11

서버를 삭제하기 위해 서버에서 무언가를 가져와야하는 것은 여전히 ​​미치게 보이지만 적어도 ID 만 다시 가져 오는 것이 전체 엔티티를 끌어내는 것보다 훨씬 느립니다.

var ids = from w in context.Widgets where w.WidgetId == widgetId select w.Id;
context.Widgets.RemoveRange(from id in ids.AsEnumerable() select new Widget { Id = id });

스텁 Widget개체에는 초기화 된 Id속성 만 있으므로 Entity Framework의 엔터티 유효성 검사에 실패 할 수 있습니다 . 이 문제를 해결하는 방법은 context.Configuration.ValidateOnSaveEnabled = false(적어도 EF6에서) 사용하는 것입니다. 이것은 Entity Framework의 자체 유효성 검사를 비활성화하지만 데이터베이스 자체의 유효성 검사는 물론 수행합니다.
Sammy S.

@SammyS. 나는 그것을 경험하지 못했기 때문에 세부 사항을 말할 수는 없지만 EF가 행을 삭제할 때 유효성 검사를 방해하는 것이 이상해 보입니다.
Edward Brey

당신은 절대적으로 맞습니다. 엔티티를로드하지 않고 ing delete하는 비슷한 해결 방법과 혼동 update했습니다.
Sammy S.

10

EF 6.1

public void DeleteWhere<TEntity>(Expression<Func<TEntity, bool>> predicate = null) 
where TEntity : class
{
    var dbSet = context.Set<TEntity>();
    if (predicate != null)
        dbSet.RemoveRange(dbSet.Where(predicate));
    else
        dbSet.RemoveRange(dbSet);

    context.SaveChanges();
} 

용법:

// Delete where condition is met.
DeleteWhere<MyEntity>(d => d.Name == "Something");

Or:

// delete all from entity
DeleteWhere<MyEntity>();

7
이것은 실제로 db.People.RemoveRange (db.People.Where (x => x.State == "CA"))와 동일합니다. db.SaveChanges (); 따라서 성능 향상이 없습니다.
ReinierDG

4

EF 4.1의 경우

var objectContext = (myEntities as IObjectContextAdapter).ObjectContext;
objectContext.ExecuteStoreCommand("delete from [myTable];");

1
이것은 작동하지만 Entity Framework 사용의 요점은 데이터베이스와 상호 작용하는 객체 지향 방식입니다. 이것은 바로 SQL 쿼리를 실행하는 것입니다.
Arturo Torres Sánchez

4

EntityFramework.Extended 또는 Z.EntityFramework.Plus.EF6과 같은 확장 라이브러리를 사용하여 EF 5, 6 또는 Core에 사용할 수 있습니다. 이러한 라이브러리는 삭제 또는 업데이트해야 할 때 성능이 뛰어나며 LINQ를 사용합니다. 삭제 예 ( source plus ) :

ctx.Users.Where(x => x.LastLoginDate < DateTime.Now.AddYears(-2)) .Delete();

또는 ( 소스 확장 )

context.Users.Where(u => u.FirstName == "firstname") .Delete();

이들은 네이티브 SQL 문을 사용하므로 성능이 뛰어납니다.


벌크 SQL 연산 생성기의 경우 600 $ +를 지불하십시오. 진심이야?
nicolay.anykienko

@ nicolay.anykienko이 라이브러리를 사용했을 때이 라이브러리는 무료였습니다. 지불해야하는 다른 작업이 있습니다. 지불
해야하는지 모르겠습니다

3

삭제하는 가장 빠른 방법은 저장 프로 시저를 사용하는 것입니다. 이름 바꾸기가 올바르게 처리되고 컴파일러 오류가 있기 때문에 동적 SQL보다 데이터베이스 프로젝트에서 저장 프로 시저를 선호합니다. 동적 SQL은 삭제되거나 이름이 바뀐 테이블을 참조하여 런타임 오류를 일으킬 수 있습니다.

이 예제에서는 두 개의 List 및 ListItems 테이블이 있습니다. 주어진 목록의 모든 ListItem을 삭제하는 빠른 방법이 필요합니다.

CREATE TABLE [act].[Lists]
(
    [Id] INT NOT NULL PRIMARY KEY IDENTITY, 
    [Name] NVARCHAR(50) NOT NULL
)
GO
CREATE UNIQUE INDEX [IU_Name] ON [act].[Lists] ([Name])
GO
CREATE TABLE [act].[ListItems]
(
    [Id] INT NOT NULL IDENTITY, 
    [ListId] INT NOT NULL, 
    [Item] NVARCHAR(100) NOT NULL, 
    CONSTRAINT PK_ListItems_Id PRIMARY KEY NONCLUSTERED (Id),
    CONSTRAINT [FK_ListItems_Lists] FOREIGN KEY ([ListId]) REFERENCES [act].[Lists]([Id]) ON DELETE CASCADE
)
go
CREATE UNIQUE CLUSTERED INDEX IX_ListItems_Item 
ON [act].[ListItems] ([ListId], [Item]); 
GO

CREATE PROCEDURE [act].[DeleteAllItemsInList]
    @listId int
AS
    DELETE FROM act.ListItems where ListId = @listId
RETURN 0

이제 확장을 사용하여 항목을 삭제하고 엔티티 프레임 워크를 업데이트하는 흥미로운 부분이 있습니다.

public static class ListExtension
{
    public static void DeleteAllListItems(this List list, ActDbContext db)
    {
        if (list.Id > 0)
        {
            var listIdParameter = new SqlParameter("ListId", list.Id);
            db.Database.ExecuteSqlCommand("[act].[DeleteAllItemsInList] @ListId", listIdParameter);
        }
        foreach (var listItem in list.ListItems.ToList())
        {
            db.Entry(listItem).State = EntityState.Detached;
        }
    }
}

메인 코드는 이제 다음과 같이 사용할 수 있습니다

[TestMethod]
public void DeleteAllItemsInListAfterSavingToDatabase()
{
    using (var db = new ActDbContext())
    {
        var listName = "TestList";
        // Clean up
        var listInDb = db.Lists.Where(r => r.Name == listName).FirstOrDefault();
        if (listInDb != null)
        {
            db.Lists.Remove(listInDb);
            db.SaveChanges();
        }

        // Test
        var list = new List() { Name = listName };
        list.ListItems.Add(new ListItem() { Item = "Item 1" });
        list.ListItems.Add(new ListItem() { Item = "Item 2" });
        db.Lists.Add(list);
        db.SaveChanges();
        listInDb = db.Lists.Find(list.Id);
        Assert.AreEqual(2, list.ListItems.Count);
        list.DeleteAllListItems(db);
        db.SaveChanges();
        listInDb = db.Lists.Find(list.Id);
        Assert.AreEqual(0, list.ListItems.Count);
    }
}

저장 프로 시저를 사용한 다음 사용법 코드를 사용하여 확장으로 구현하는 좋은 예를 주셔서 감사합니다.
glenn garson

3

테이블의 모든 행을 삭제하려면 sql 명령을 실행할 수 있습니다

using (var context = new DataDb())
{
     context.Database.ExecuteSqlCommand("TRUNCATE TABLE [TableName]");
}

TRUNCATE TABLE (Transact-SQL) 개별 행 삭제를 기록하지 않고 테이블에서 모든 행을 제거합니다. TRUNCATE TABLE은 WHERE 절이없는 DELETE 문과 유사합니다. 그러나 TRUNCATE TABLE은 더 빠르며 더 적은 시스템 및 트랜잭션 로그 리소스를 사용합니다.


3
또한 truncate tableFOREIGN KEY 제약 조건에 의해 참조되는 테이블 에서는 실행할 수 없습니다 . 자신을 참조하는 외래 키가있는 테이블을자를 수 있습니다. MSDN 설명서
광대역

2

UUHHIVS배치 삭제를위한 매우 우아하고 빠른 방법이지만주의해서 사용해야합니다.

  • 트랜잭션 자동 생성 : 쿼리에 트랜잭션이 포함됩니다.
  • 데이터베이스 컨텍스트 독립성 : 실행과 관련이 없습니다. context.SaveChanges()

이러한 문제는 거래를 통제함으로써 회피 할 수 있습니다. 다음 코드는 트랜잭션 방식으로 일괄 삭제 및 대량 삽입을 배치하는 방법을 보여줍니다.

var repo = DataAccess.EntityRepository;
var existingData = repo.All.Where(x => x.ParentId == parentId);  

TransactionScope scope = null;
try
{
    // this starts the outer transaction 
    using (scope = new TransactionScope(TransactionScopeOption.Required))
    {
        // this starts and commits an inner transaction
        existingData.Delete();

        // var toInsert = ... 

        // this relies on EntityFramework.BulkInsert library
        repo.BulkInsert(toInsert);

        // any other context changes can be performed

        // this starts and commit an inner transaction
        DataAccess.SaveChanges();

        // this commit the outer transaction
        scope.Complete();
    }
}
catch (Exception exc)
{
    // this also rollbacks any pending transactions
    scope?.Dispose();
}

2

엔터티 프레임 워크 코어

3.1 3.0 2.2 2.1 2.0 1.1 1.0

using (YourContext context = new YourContext ())
{
    var widgets = context.Widgets.Where(w => w.WidgetId == widgetId);
    context.Widgets.RemoveRange(widgets);
    context.SaveChanges();
}

요약 :

SaveChanges가 호출 될 때 데이터베이스에서 삭제되도록 각 엔티티가 삭제됨 상태에있는 세트의 기본 컨텍스트에서 제공된 엔티티 콜렉션을 제거합니다.

비고 :

System.Data.Entity.Infrastructure.DbContextConfiguration.AutoDetectChangesEnabled가 기본값 (기본값)으로 설정된 경우 엔티티를 삭제하기 전에 DetectChanges가 한 번 호출되며 다시 호출되지 않습니다. 이는 일부 상황에서 RemoveRange가 Remove를 여러 번 호출하는 것보다 훨씬 더 나은 성능을 발휘할 수 있음을 의미합니다. 추가 된 상태의 컨텍스트에 엔티티가 존재하면이 메소드로 인해 엔티티가 컨텍스트에서 분리됩니다. 데이터베이스에 추가 된 엔티티가 존재하지 않는 것으로 가정하여 삭제하려고 시도하는 것이 의미가 없기 때문입니다.


1

다음과 같이 SQL 쿼리를 직접 실행할 수 있습니다.

    private int DeleteData()
{
    using (var ctx = new MyEntities(this.ConnectionString))
    {
        if (ctx != null)
        {

            //Delete command
            return ctx.ExecuteStoreCommand("DELETE FROM ALARM WHERE AlarmID > 100");

        }
    }
    return 0;
}

선택을 위해 우리는 사용할 수 있습니다

using (var context = new MyContext()) 
{ 
    var blogs = context.MyTable.SqlQuery("SELECT * FROM dbo.MyTable").ToList(); 
}

EF가 삭제 조건 매핑을 제대로 지원하지 않는 경우 작업을 완료하는 것이 가장 좋습니다.
Tony O'Hagan

1

또한 DeleteAllOnSubmit () 메서드 를 var가 아닌 일반 목록으로 결과를 전달 하여 사용할 수 있습니다 . 이렇게하면 foreach가 한 줄의 코드로 줄어 듭니다.

List<Widgets> widgetList = context.Widgets
              .Where(w => w.WidgetId == widgetId).ToList<Widgets>();

context.Widgets.DeleteAllOnSubmit(widgetList);

context.SubmitChanges();

그래도 여전히 내부적으로 루프를 사용합니다.


3
당신이 무엇인지 오해하고있는 var것 같습니다.
freedomn-m

1

Thanh의 답변이 가장 효과적이었습니다. 단일 서버 트립에서 내 레코드를 모두 삭제했습니다. 실제로 확장 방법을 호출하는 데 어려움을 겪었으므로 공유 할 것이라고 생각했습니다 (EF 6).

내 MVC 프로젝트의 도우미 클래스에 확장 메서드를 추가하고 이름을 "RemoveWhere"로 변경했습니다. 내 컨트롤러에 dbContext를 삽입하지만을 수행 할 수도 있습니다 using.

// make a list of items to delete or just use conditionals against fields
var idsToFilter = dbContext.Products
    .Where(p => p.IsExpired)
    .Select(p => p.ProductId)
    .ToList();

// build the expression
Expression<Func<Product, bool>> deleteList = 
    (a) => idsToFilter.Contains(a.ProductId);

// Run the extension method (make sure you have `using namespace` at the top)
dbContext.RemoveWhere(deleteList);

그룹에 대해 단일 삭제 문이 생성되었습니다.


0

EF 6. =>

var assignmentAddedContent = dbHazirBot.tbl_AssignmentAddedContent.Where(a =>
a.HazirBot_CategoryAssignmentID == categoryAssignment.HazirBot_CategoryAssignmentID);
dbHazirBot.tbl_AssignmentAddedContent.RemoveRange(assignmentAddedContent);
dbHazirBot.SaveChanges();

0

베스트 : in EF6 => .RemoveRange()

예:

db.Table.RemoveRange(db.Table.Where(x => Field == "Something"));

14
이것은 카일의 대답과 어떻게 다릅니 까?

-1

작동하는 '좋아하는 코드 비트'답변보기

내가 사용한 방법은 다음과 같습니다.

     // Delete all rows from the WebLog table via the EF database context object
    // using a where clause that returns an IEnumerable typed list WebLog class 
    public IEnumerable<WebLog> DeleteAllWebLogEntries()
    {
        IEnumerable<WebLog> myEntities = context.WebLog.Where(e => e.WebLog_ID > 0);
        context.WebLog.RemoveRange(myEntities);
        context.SaveChanges();

        return myEntities;
    }

1
답변이 user1308743 답변과 어떻게 다릅니 까?
Sergey Berezovskiy 2019

나는 단순히 실례를 공유하고있었습니다. 내가 여기있는 도움을 돌려주기 위해 할 수있는 일
Brian Quinn

-3

EF 6.2에서 이것은 엔티티를 먼저로드하지 않고 데이터베이스에 직접 삭제를 전송하여 완벽하게 작동합니다.

context.Widgets.Where(predicate).Delete();

고정 술어를 사용하면 매우 간단합니다.

context.Widgets.Where(w => w.WidgetId == widgetId).Delete();

그리고 동적 술어가 필요하다면 LINQKit (Nuget package available)를 살펴보십시오 . 제 경우에는 다음과 같이 작동합니다.

Expression<Func<Widget, bool>> predicate = PredicateBuilder.New<Widget>(x => x.UserID == userID);
if (somePropertyValue != null)
{
    predicate = predicate.And(w => w.SomeProperty == somePropertyValue);
}
context.Widgets.Where(predicate).Delete();

1
원시 EF 6.2에서는 불가능합니다. 어쩌면 당신은 Z.EntityFramework.Plus비슷한 것을 사용 하고 있습니까? ( entityframework.net/batch-delete )
Sammy S.

첫 번째는 원시 EF 6.2이며 작동합니다. 두 번째는 LINQKit을 사용하는 것입니다.
블라디미르

1
흠, 나는이 방법을 찾을 수 없습니다. 이 메소드가 상주하는 클래스와 네임 스페이스를 확인할 수 있습니까?
Sammy S.

세 번째입니다 ( Delete()방법은 본질적으로 존재하지 않습니다).
합계 없음
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.