Entity Framework'teki birden çok satırı nasıl silebilirim (foreach olmadan)


305

Entity Framework kullanarak bir tablodan birkaç öğe siliyorum. Yabancı bir anahtar / üst nesne yok, bu yüzden OnDeleteCascade ile bu işleyemezsiniz.

Şu anda bunu yapıyorum:

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

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

Çalışıyor ama foreach beni rahatsız ediyor. EF4 kullanıyorum ama SQL yürütmek istemiyorum. Ben sadece bir şey eksik olmadığından emin olmak istiyorum - bu kadar iyi, değil mi? Bir uzatma yöntemi veya yardımcısı ile soyutlayabilirim, ancak bir yerde hala bir foreach yapacağız, değil mi?


1
Kabul edilen cevabı tekrar ziyaret etmek isteyebilirsiniz.
Eric J.

1
Performanslı kalmak istiyorsanız belki cevabımı burada kontrol etmek isteyebilirsiniz stackoverflow.com/a/35033286/274589
Adi

Yanıtlar:


49

SQL'i doğrudan bir döngüde DeleteObject'i çağırmak istemiyorsanız, bugün yapabileceğiniz en iyisidir.

Bununla birlikte, burada açıkladığım yaklaşımı kullanarak SQL'yi yürütebilir ve yine de bir uzantı yöntemi aracılığıyla tamamen genel bir amaç haline getirebilirsiniz .

Her ne kadar bu cevap 3.5 idi. 4.0 için StoreConnection'a gitmek yerine büyük olasılıkla yeni ExecuteStoreCommand API'sini kullanacağım.


ExecuteStoreCommand uygun bir yol değildir.DeleteAllSubmit linq to sql içinde çalışıyor ancak varlık çerçevesinde çalışmıyor. Varlık çerçevesinde aynı seçeneği istiyorum.
Hiral

653

EntityFramework 6 bunu biraz daha kolaylaştırdı .RemoveRange().

Misal:

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

31
Tam olarak ihtiyacımız olan şey ... Yeterince geniş bir aralıkta kullandığım sürece, bellek yetersiz bir istisna alıyorum! RemoveRange'ın asıl amacının işleme veritabanına geçmesi olduğunu düşündüm, ama görünüşe göre değil.
Samer Adra

Bu WAAAYYYY her varlık için Silinmiş durumunu ayarlamak daha hızlı!
Jerther

54
Kesinlikle bu cevap daha kolay ama performans açısından harika olmayabilir. Neden? Bu exatly doet, foreach döngüsünde silmekle aynıdır, önce tüm satırları alır ve sonra teker teker siler, yalnızca kazanç "Herhangi bir varlığı silmeden önce bir kez DetectChanges çağrılır ve tekrar çağrılmayacaktır" aynı, oluşturulan sql görmek için aracını kullanmayı deneyin.
Anshul Nigam

6
Yeterince büyük bir aralığı için, RemoveRange (...) kadar sökünüz gibi bir şey (10000) ve döngü deneyin) (== 0 sayın.
Eric J.

20
Sorun, RemoveRange giriş parametresinin IEnumerable olması, bu nedenle silme işlemini gerçekleştirmek için tüm varlıkları numaralandırır ve varlık başına 1 DELETE sorgusu çalıştırır.
bubi

74

bu kadar iyi, değil mi? Bir uzatma yöntemi veya yardımcısı ile soyutlayabilirim, ancak bir yerde hala bir foreach yapacağız, değil mi?

Evet, ancak iki astarlı yapabilirsiniz:

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

76
Amacı yenen bir ToList () yapıyorsunuz. Orijinal çözümden farkı nedir?
lahsrah

3
Bağlam nesnesinde yalnızca Remove yöntemi olduğundan sorun yaşıyorum.
13

2
Bir milyon satır (hatta birkaç yüz) beklendiğinde bu kesinlikle uygun bir çözüm değildir. Ancak, yalnızca birkaç satır olacağını kesin olarak bilersek, bu çözüm düzgün ve mükemmel bir şekilde çalışır. Evet, DB'ye birkaç gidiş-dönüş yolculuğu içerecektir, ancak bence SQL çağrısında yer alan kayıp soyutlama doğrudan faydalardan ağır basmaktadır.
Yogster

Entity Framework, adından da anlaşılacağı gibi, varlık düzeyindeki verilerle en iyi şekilde çalışır. Toplu veri işlemleri en iyi şekilde iyi eski depolanmış işlemler tarafından gerçekleştirilir. Performans açısından onlar en iyi seçenek ve bir döngü gerektiren herhangi bir EF mantığı yenecek.
Paceman

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

Ancak bunu bir kimlik listesi ile nasıl yapabilirsiniz? Bu çözüm "listeleri" çok iyi işlemez.
JesseNewman19

11
@ JesseNewman19 Zaten bir kimlik listeniz varsa, a kullanın WHERE IN ({0})ve sonra ikinci argüman olmalıdır String.Join(",", idList).
Langdon

@Langdon çalışmaz, çünkü komutu sql'e şu şekilde gönderir: WHERE IN ("1, 2, 3"). Veritabanı, bir tamsayı listesi yerine bir dize geçirdiğiniz için bir hata atar.
JesseNewman19

LINQ ile böyle bir ifade oluşturmak istiyorum. Bulduğum en yakın şey bir lib. EntityFramework.Extended
Jaider

Kullanıyorsanız , önceden oluşturulmuş SQL dizesini kullanmanız ve komuta iletmeniz String.Joingerekebilir string.Format. Listenizde yalnızca tamsayılar olduğu sürece, enjeksiyon saldırısı riski yoktur. Bu soruyu kontrol edin: bir diziyi execute store komutuna nasıl iletebilirim?
Andrew

50

Oldukça geç olduğunu biliyorum, ancak birinin basit bir çözüme ihtiyacı varsa, havalı şey de onunla nerede maddeyi ekleyebilirsiniz:

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);
}

Not: MSSQL2008 ile test edilmiştir.

Güncelleme:

EF, parametrelerle sql deyimi oluşturduğunda yukarıdaki çözüm çalışmaz , bu nedenle EF5 için güncelleme :

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);
}

Biraz yansıma gerektirir, ancak iyi çalışır.


DbContext nedir? Otomatik olarak oluşturulmuş varlık çerçevesi içeriğiniz var mı? Set <T> adlı bir yöntemim yok.
Stealth Haham

@Stealth: Evet, bu sizin EF veri içeriğiniz, önce kod kullanıyorum ama otomatik oluşturulan içerik aynı olmalı. Yanlış yazılmış ifade için üzgünüm Set <T> () (şirketim internet erişimi retricts Ben kodu yapıştıramadı, elle yazmak zorunda kaldım ...), kodları güncellenmiş :)
Thanh Nguyen

3
Bu soruya gerçekten cevap veren tek cevap bu! Diğer her yanıt, her bir öğeyi birer birer siler, inanılmaz.
Rocklan

Bu en doğru cevap gibi geliyor. Çok genel bir şekilde silmeye izin verir ve işi C # yerine veritabanına düzgün bir şekilde yükler.
JesseNewman19

1
Orada daha az teknik programcılar için, bu mükemmel ve genel çözümün nasıl uygulanacağı hakkında biraz daha ayrıntıya girmek istedim, çünkü bu beni birkaç dakika kazandıracaktı! Bir sonraki yorumda devam ...
jdnew18

30

EF5 kullanan herkes için aşağıdaki uzantı kitaplığı kullanılabilir: https://github.com/loresoft/EntityFramework.Extended

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

3
Durumumda kullanılamayan büyük tablolarda performans sorunları var.
Tomas

@Tomas ne tür bir perfromans yayınladı? Sorun ne kadar şiddetliydi ve Tablo ne kadar büyüktü? Başka kimse bunu onaylayabilir mi?
Anestis Kivranoglou

Oradaki alternatiflere kıyasla gerçekten hızlı
Jaider

Göremiyorum Delete()Ef6 benim varlıklar işlevini kullanın.
dotNET

context.Widgets.Where(w => w.WidgetId == widgetId).Delete();EntityFramework.Extended ile yeni bir yoldur
Peter Kerr

11

Yine de silmek için sunucudan herhangi bir şey geri almak zorunda olmak çılgınca görünüyor, ancak en azından sadece kimlikleri geri almak, tüm varlıkları aşağı çekmekten çok daha zayıf:

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 });

Dikkatli olun - saplama Widgetnesneleriniz yalnızca başlatılmış bir Idözelliğe sahip olduğundan Entity Framework'ün varlık doğrulamasında başarısız olabilir . Bunun yolu kullanmaktır context.Configuration.ValidateOnSaveEnabled = false(en azından EF6'da). Bu, Entity Framework'ün kendi doğrulamasını devre dışı bırakır, ancak yine de veritabanının kendi doğrulamasını gerçekleştirir.
Sammy S.

@SammyS. Bunu deneyimlemedim, bu yüzden detaylarla konuşamıyorum, ancak EF, satırı yine de silerken doğrulama ile uğraşması tuhaf görünüyor.
Edward Brey

Kesinlikle haklısın. Varlıkları yüklemeden ing deleteiçin benzer bir çözümle karıştırdım update.
Sammy

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();
} 

Kullanımı:

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

Or:

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

7
Bu etkin bir şekilde db.People.RemoveRange (db.People.Where (x => x.State == "CA")); db.SaveChanges (); Yani performans kazancı yok.
ReinierDG

4

EF 4.1 için,

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

1
Bu işe yarar, ancak Entity Framework'ü kullanmanın tüm amacı, veritabanıyla etkileşim kurmak için nesne yönelimli bir yöntem kullanmaktır. Bu sadece doğrudan SQL sorgusu çalıştırıyor.
Arturo Torres Sánchez

4

Bunu yapmak için EntityFramework.Extended veya Z.EntityFramework.Plus.EF6 gibi uzantı kütüphanelerini kullanabilirsiniz, EF 5, 6 veya Core için kullanılabilir. Bu kütüphaneler, silmeniz veya güncellemeniz gerektiğinde mükemmel performans gösterir ve LINQ kullanır. Silme örneği ( kaynak artı ):

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

veya ( kaynak genişletildi )

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

Bunlar yerel SQL ifadeleri kullanır, bu nedenle performans mükemmeldir.


Toplu sql operasyon jeneratörü için 600 $ + ödeyin. Ciddi anlamda?
nicolay.anykienko

@ nicolay.anykienko Onu kullandığımda, bu kütüphane ücretsizdi, ödemek zorunda olduğunuz diğer işlemler var, değil mi ödemek zorunda bilmiyorum
UUHHIVS

3

Silmenin en hızlı yolu saklı bir yordam kullanmaktır. Dinamik SQL yerine bir veritabanı projesinde saklı yordamlar tercih çünkü isimleri doğru ele alınacak ve derleyici hataları var. Dinamik SQL, çalışma zamanı hatalarına neden olan silinen / yeniden adlandırılan tablolara başvurabilir.

Bu örnekte, List ve ListItems adlı iki tablo var. Belirli bir listenin tüm ListItems silmek için hızlı bir yol gerekir.

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

Şimdi öğeleri silmenin ve Varlık çerçevesini bir uzantı kullanarak güncellemenin ilginç kısmı.

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;
        }
    }
}

Ana kod şimdi kullanabilirsiniz gibi

[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);
    }
}

Saklı Yordam'ı kullanmanın ve ardından Kullanım koduyla uzantı olarak uygulamanızın güzel bir örneği için teşekkür ederiz.
glenn garson

3

Bir tablonun tüm satırlarını silmek istiyorsanız, sql komutunu yürütebilirsiniz

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

TRUNCATE TABLE (Transact-SQL) Tek tek satır silme işlemlerini kaydetmeden tablodaki tüm satırları kaldırır. TRUNCATE TABLE, WHERE deyimi olmayan DELETE deyimine benzer; ancak, TRUNCATE TABLE daha hızlıdır ve daha az sistem ve işlem günlüğü kaynağı kullanır.


3
truncate tableBir FOREIGN KEY kısıtlaması tarafından başvurulan tablolarda çalışamayacağınızdan da bahsetmelisiniz . (Kendisine başvuran yabancı anahtar içeren bir tabloyu kısaltabilirsiniz.). MSDN belgeleri
geniş bant

2

UUHHIVS's, toplu silme için çok zarif ve hızlı bir yoldur, ancak dikkatli kullanılmalıdır:

  • otomatik işlem oluşturma: sorguları bir işlem tarafından kapsanacaktır
  • veritabanı bağlam bağımsızlığı: yürütme ile ilgisi yoktur context.SaveChanges()

Bu sorunlar, işlemin kontrolünü ele alarak atlatılabilir. Aşağıdaki kod, toplu silme ve toplu ekleme işlemlerini nasıl gerçekleştireceğinizi gösterir:

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

Varlık Çerçevesi Çekirdeği

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();
}

Özet :

Verilen varlık koleksiyonunu, SaveChanges çağrıldığında her bir varlık Silinmiş durumuna konacak şekilde kümenin altındaki bağlamdan kaldırır.

Açıklamalar :

System.Data.Entity.Infrastructure.DbContextConfiguration.AutoDetectChangesEnabled öğesi true (varsayılan değer) olarak ayarlanırsa, DetectChanges öğelerin silinmeden önce bir kez çağrılacağını ve bir daha çağrılmayacağını unutmayın. Bu, bazı durumlarda RemoveRange işlevinin birden çok kez Kaldır çağrısından çok daha iyi performans gösterebileceği anlamına gelir. Eklenen durumda bağlamda herhangi bir varlık varsa, bu yöntemin söz konusu öğenin bağlamdan ayrılmasına neden olacağını unutmayın. Bunun nedeni, eklenen bir varlığın veritabanında silinmeye çalışılmasının mantıklı olmayacağı şekilde varsayıldığıdır.


1

Doğrudan sql sorgularını aşağıdaki gibi yürütebilirsiniz:

    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;
}

Seçmek için kullanabiliriz

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

EF'nin silme koşullarının eşlenmesini düzgün bir şekilde desteklemediği göz önüne alındığında, bu muhtemelen işi yapmak için en iyi seçenektir.
Tony O'Hagan

1

Sonuçlarınızı var yerine genel bir listeye ileterek DeleteAllOnSubmit () yöntemini de kullanabilirsiniz . Bu şekilde ön kodunuz bir kod satırına düşer:

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

context.Widgets.DeleteAllOnSubmit(widgetList);

context.SubmitChanges();

Muhtemelen hala dahili olarak bir döngü kullanıyor.


3
Görünüşe göre a'nın ne olduğunu yanlış anlıyorsunuz var.
freedomn-m

1

Thanh'ın cevabı benim için en iyi sonucu verdi. Tüm kayıtlarımı tek bir sunucu gezisinde sildim. Aslında uzatma yöntemini çağırmakla uğraştım, bu yüzden benimkini paylaşacağımı düşündüm (EF 6):

MVC projemdeki bir yardımcı sınıfa genişletme yöntemini ekledim ve adı "RemoveWhere" olarak değiştirdim. Denetleyicilerime bir dbContext enjekte ediyorum, ancak bir de yapabilirsiniz 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);

Bu, grup için tek bir silme ifadesi oluşturdu.


0

EF 6. =>

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

0

En iyi : in EF6 => .RemoveRange()

Misal:

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

14
Bu Kyle'ın cevabından nasıl farklı?

-1

Çalışan 'favori kod parçası' cevabına bakın

İşte nasıl kullandım:

     // 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
Cevabınız user1308743 yanıtından nasıl farklıdır ?
Sergey Berezovskiy

Sadece çalışan bir örneği paylaşıyordum. Buraya gelen yardım için geri vermek için ne yapabilirsem.
Brian Quinn

-3

EF 6.2'de bu mükemmel bir şekilde çalışır ve silmeyi önce varlıkları yüklemeden doğrudan veritabanına gönderir:

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

Sabit bir yüklem ile oldukça basittir:

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

Ve dinamik bir yüklemeye ihtiyacınız varsa LINQKit'e (Nuget paketi mevcut) bir göz atın , böyle bir şey benim durumumda iyi çalışır:

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
Ham EF 6.2 ile bu mümkün değildir. Belki kullanıyorsunuz Z.EntityFramework.Plusya da benzer bir şey? ( entityframework.net/batch-delete )
Sammy S.

Birincisi ham EF 6.2 ve iş bulmak. İkincisi, dediğim gibi LINQKit kullanmak.
Vladimir

1
Hmm, bu yöntemi bulamıyorum. Bu yöntemin hangi sınıfta ve hangi ad alanında bulunduğunu kontrol edebilir misiniz?
Sammy

Delete()Üçüncüyüm ( yöntem doğal olarak mevcut değildir).
Toplam Yok
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.