Làm cách nào để xóa nhiều hàng trong Entity Framework (không có foreach)


305

Tôi đang xóa một số mục từ bảng bằng Entity Framework. Không có đối tượng khóa / đối tượng cha mẹ ngoại nên tôi không thể xử lý việc này với OnDeleteCascade.

Ngay bây giờ tôi đang làm điều này:

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

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

Nó hoạt động nhưng foreach lỗi tôi. Tôi đang sử dụng EF4 nhưng tôi không muốn thực thi SQL. Tôi chỉ muốn chắc chắn rằng tôi không bỏ lỡ bất cứ điều gì - điều này là tốt như nó được, phải không? Tôi có thể trừu tượng hóa nó bằng một phương thức mở rộng hoặc người trợ giúp, nhưng ở đâu đó chúng ta vẫn sẽ thực hiện một bài thuyết minh, phải không?


1
Bạn có thể muốn xem lại câu trả lời được chấp nhận.
Eric J.

1
Nếu bạn muốn duy trì hiệu suất, có lẽ bạn có thể muốn kiểm tra câu trả lời của tôi ở đây stackoverflow.com/a/35033286/274589
Adi

Câu trả lời:


49

Nếu bạn không muốn thực thi SQL gọi trực tiếp DeleteObject trong một vòng lặp là cách tốt nhất bạn có thể làm hôm nay.

Tuy nhiên, bạn có thể thực thi SQL và vẫn làm cho nó hoàn toàn có mục đích chung thông qua một phương thức mở rộng, sử dụng phương pháp tôi mô tả ở đây .

Mặc dù câu trả lời đó là cho 3,5. Đối với 4.0, tôi có thể sẽ sử dụng API ExecuteStoreCommand mới trong phần mềm thay vì thả xuống StoreConnection.


ExecuteStoreCommand không phải là một cách thích hợp.DeleteAllSubmit đang làm việc trong linq đến sql nhưng không phải trong khung thực thể. Tôi muốn cùng tùy chọn trong khung thực thể.
Hirus

653

EntityFramework 6 đã làm điều này dễ dàng hơn một chút với .RemoveRange().

Thí dụ:

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

31
Đó chính xác là những gì chúng ta cần ... Ngoại trừ khi tôi sử dụng nó trên một phạm vi đủ lớn, tôi nhận được một ngoại lệ ngoài bộ nhớ! Tôi nghĩ rằng toàn bộ quan điểm của RemoveRange là chuyển việc xử lý vào cơ sở dữ liệu, nhưng dường như là không.
Samer Adra

Đây là WAAAYYYY nhanh hơn việc đặt trạng thái Đã xóa cho mọi thực thể!
Jerther

54
Để chắc chắn câu trả lời này dễ dàng hơn nhưng hiệu suất khôn ngoan thì nó có thể không tuyệt vời. Tại sao? những gì doet exatly này giống như xóa nó trong vòng lặp foreach, trước tiên nó tìm nạp tất cả các hàng và sau đó xóa từng cái một, chỉ đạt được là để lưu "DetectChanges sẽ được gọi một lần trước khi xóa bất kỳ thực thể nào và sẽ không được gọi lại" là như vậy, hãy thử sử dụng công cụ để xem sql được tạo.
Anshul Nigam

6
Đối với phạm vi đủ lớn, hãy thử một cái gì đó như .Take (10000) và lặp cho đến khi RemoveRange (...). Count () == 0.
Eric J.

20
Vấn đề là tham số đầu vào RemoveRange là một IEnumerable để thực hiện xóa nó liệt kê tất cả các thực thể và chạy 1 truy vấn XÓA trên mỗi thực thể.
bubi 17/03/2015

74

Điều này là tốt như nó được, phải không? Tôi có thể trừu tượng hóa nó bằng một phương thức mở rộng hoặc người trợ giúp, nhưng ở đâu đó chúng ta vẫn sẽ thực hiện một bài thuyết minh, phải không?

Vâng, vâng, ngoại trừ bạn có thể làm cho nó thành một hai lớp:

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

76
Bạn đang thực hiện một ToList () đánh bại mục đích. Làm thế nào là khác nhau từ các giải pháp ban đầu?
lahsrah

3
Tôi có vấn đề vì tôi chỉ có phương thức Remove trong đối tượng bối cảnh.
Pnct

2
Đây chắc chắn không phải là một giải pháp phù hợp khi một triệu hàng (hoặc thậm chí vài trăm) được mong đợi. Tuy nhiên nếu chúng ta biết chắc chắn sẽ chỉ có một vài hàng thì giải pháp này gọn gàng và hoạt động hoàn hảo. Đúng, nó sẽ liên quan đến một vài chuyến đi khứ hồi tới DB, nhưng theo tôi, sự trừu tượng bị mất liên quan đến việc gọi SQL trực tiếp vượt xa lợi ích.
Yogster 17/12/14

Entity Framework, như tên cho thấy, hoạt động tốt nhất với dữ liệu ở cấp thực thể. Hoạt động dữ liệu hàng loạt được xử lý tốt nhất bởi các procs lưu trữ cũ tốt. Về mặt hiệu năng, chúng là những lựa chọn tốt nhất và sẽ đánh bại bất kỳ logic EF nào cần một vòng lặp.
Paceman

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

Nhưng làm thế nào bạn có thể làm điều này với một danh sách các id? Giải pháp này không xử lý "danh sách" rất tốt.
JesseNewman19

11
@ JesseNewman19 Nếu bạn đã có một danh sách ID, hãy sử dụng a WHERE IN ({0}), và sau đó đối số thứ hai sẽ là String.Join(",", idList).
Langdon

@Langdon sẽ không hoạt động, vì nó sẽ gửi lệnh tới sql như vậy: WHERE IN ("1, 2, 3"). Cơ sở dữ liệu sau đó đưa ra một lỗi vì bạn đã truyền cho nó một chuỗi thay vì danh sách các số nguyên.
JesseNewman19

Tôi muốn tạo ra một tuyên bố như vậy với LINQ. Điều gần nhất tôi tìm thấy là một lib. EntityFramework.Extended
Jaider

Nếu bạn đang sử dụng String.Join, bạn có thể cần phải sử dụng string.Formatvà chuyển chuỗi SQL đã được tạo thành cho lệnh. Miễn là danh sách của bạn chỉ có số nguyên, không có nguy cơ bị tấn công tiêm. Kiểm tra câu hỏi này: làm thế nào tôi có thể truyền một mảng cho lệnh lưu trữ thực thi?
Andrew

50

Tôi biết nó khá muộn nhưng trong trường hợp ai đó cần một giải pháp đơn giản, điều thú vị là bạn cũng có thể thêm mệnh đề where với nó:

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

Lưu ý: vừa được thử nghiệm với MSSQL2008.

Cập nhật:

Giải pháp ở trên sẽ không hoạt động khi EF tạo câu lệnh sql với các tham số , vì vậy đây là bản cập nhật cho 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);
}

Nó đòi hỏi một chút suy ngẫm nhưng hoạt động tốt.


DbContext là gì? Tôi giả sử bối cảnh khung thực thể tự động tạo của bạn? Tôi không có một phương thức gọi là Đặt <T>.
Rabbi tàng hình

@Stealth: Vâng, đó là bối cảnh dữ liệu EF của bạn, tôi sử dụng mã đầu tiên nhưng bối cảnh được tạo tự động phải giống nhau. Xin lỗi vì tuyên bố gõ sai nên được đặt <T> () (công ty của tôi hạn chế truy cập internet Tôi không thể dán mã, phải nhập bằng tay nên ...), mã được cập nhật :)
Thanh Nguyen

3
Đây là câu trả lời duy nhất thực sự trả lời câu hỏi! Mỗi câu trả lời khác xóa từng mục một, không thể tin được.
Rocklan

Điều này cảm thấy như câu trả lời đúng nhất. Nó cho phép xóa theo một cách rất chung chung và nó sẽ giảm tải công việc cho cơ sở dữ liệu chứ không phải C #.
JesseNewman19

1
Đối với tất cả các lập trình viên ít kỹ thuật ngoài kia, tôi muốn giải thích thêm một chút về cách thực hiện giải pháp tuyệt vời và chung chung này, bởi vì nó sẽ giúp tôi tiết kiệm được một vài phút! Tiếp tục trong bình luận tiếp theo ...
jdew18

30

Đối với bất kỳ ai sử dụng EF5, thư viện tiện ích mở rộng sau đây có thể được sử dụng: https://github.com/loresoft/EntityFramework.Extends

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

3
Có vấn đề về hiệu suất trên các bảng lớn, không thể sử dụng trong tình huống của tôi.
Tomas

@Tomas bạn đã nhận thấy loại thông báo nào? Vấn đề nghiêm trọng đến mức nào và trên Bảng lớn như thế nào? Bất cứ ai khác có thể xác nhận điều đó?
Anestis Kivranoglou 16/2/2016

Nó thực sự nhanh so với các lựa chọn thay thế ngoài kia
Jaider

Tôi không thể thấy Delete()chức năng trong các thực thể của mình trong EF6.
dotNET

context.Widgets.Where(w => w.WidgetId == widgetId).Delete();là cách mới hơn với EntityFramework.Extends
Peter Kerr

11

Vẫn có vẻ điên rồ khi phải lấy lại bất cứ thứ gì từ máy chủ chỉ để xóa nó, nhưng ít nhất chỉ lấy lại được ID thì gọn gàng hơn nhiều so với việc kéo xuống các thực thể đầy đủ:

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

Hãy cẩn thận - điều này có thể không xác thực thực thể của Entity Framework vì các Widgetđối tượng sơ khai của bạn chỉ có một thuộc tính được khởi tạo Id. Cách xung quanh này là sử dụng context.Configuration.ValidateOnSaveEnabled = false(ít nhất là trong EF6). Điều này vô hiệu hóa xác thực riêng của Entity Framework, nhưng vẫn thực hiện khóa xác thực của cơ sở dữ liệu.
Sammy S.

@SammyS. Tôi chưa có kinh nghiệm về điều đó, vì vậy không thể nói chi tiết, nhưng có vẻ kỳ lạ là EF sẽ bận tâm đến việc xác nhận khi nó vẫn xóa hàng.
Edward Brey

Bạn hoàn toàn chính xác. Tôi đã nhầm lẫn deletevới một cách giải quyết tương tự cho updatecác thực thể ing mà không tải chúng.
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();
} 

Sử dụng:

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

Or:

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

7
Điều này thực sự giống như db.P People.RemoveRange (db.P People.Where (x => x.State == "CA")); db.SaveChanges (); Vì vậy, không có hiệu suất đạt được.
RebierDG

4

Đối với EF 4.1,

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

1
Điều này hoạt động, nhưng toàn bộ quan điểm sử dụng Entity Framework đang có một cách hướng đối tượng để tương tác với cơ sở dữ liệu. Đây chỉ là trực tiếp chạy truy vấn SQL.
Arturo Torres Sánchez

4

Bạn có thể sử dụng các thư viện tiện ích mở rộng để thực hiện điều đó như EntityFramework.Extends hoặc Z.EntityFramework.Plus.EF6, có sẵn cho EF 5, 6 hoặc Core. Các thư viện này có hiệu suất tuyệt vời khi bạn phải xóa hoặc cập nhật và họ sử dụng LINQ. Ví dụ để xóa ( nguồn cộng ):

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

hoặc ( nguồn mở rộng )

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

Chúng sử dụng các câu lệnh SQL gốc, vì vậy hiệu suất là tuyệt vời.


Trả 600 $ + cho máy phát hoạt động sql số lượng lớn. Nghiêm túc?
nicolay.anykienko

@ nicolay.anykienko Khi tôi sử dụng, thư viện này miễn phí, có những hoạt động khác mà bạn phải trả tiền, phải không tôi không biết bạn có phải trả tiền không
UUHHIVS

3

Cách nhanh nhất để xóa là sử dụng một thủ tục được lưu trữ. Tôi thích các thủ tục được lưu trữ trong một dự án cơ sở dữ liệu hơn SQL động vì việc đổi tên sẽ được xử lý chính xác và có lỗi trình biên dịch. SQL động có thể tham chiếu đến các bảng đã bị xóa / đổi tên gây ra lỗi thời gian chạy.

Trong ví dụ này, tôi có hai bảng List và ListItems. Tôi cần một cách nhanh chóng để xóa tất cả các ListItems của một danh sách nhất định.

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

Bây giờ là phần thú vị của việc xóa các mục và cập nhật khung Thực thể bằng cách sử dụng tiện ích mở rộng.

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

Mã chính bây giờ có thể sử dụng nó là

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

Cảm ơn bạn về một ví dụ hay về việc sử dụng Quy trình được lưu trữ, và sau đó triển khai nó dưới dạng tiện ích mở rộng, với mã Sử dụng.
glenn garson

3

Nếu bạn muốn xóa tất cả các hàng của bảng, bạn có thể thực thi lệnh sql

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

BẢNG TRUNCATE (Transact-SQL) Xóa tất cả các hàng khỏi bảng mà không ghi nhật ký xóa hàng riêng lẻ. TRUNCATE TABLE tương tự như câu lệnh DELETE không có mệnh đề WHERE; tuy nhiên, TRUNCATE TABLE nhanh hơn và sử dụng ít tài nguyên nhật ký giao dịch và hệ thống hơn.


3
Bạn cũng nên đề cập rằng bạn không thể chạy truncate tabletrên các bảng được tham chiếu bởi ràng buộc FOREIGN KEY. (Bạn có thể cắt bớt một bảng có khóa ngoại tham chiếu chính nó.). Tài liệu MSDN
băng thông rộng

2

UUHHIVSĐây là một cách rất thanh lịch và nhanh chóng để xóa hàng loạt, nhưng nó phải được sử dụng cẩn thận:

  • tự động tạo giao dịch: các truy vấn của nó sẽ được bao gồm bởi một giao dịch
  • độc lập bối cảnh cơ sở dữ liệu: việc thực thi của nó không liên quan gì context.SaveChanges()

Những vấn đề này có thể được phá vỡ bằng cách kiểm soát giao dịch. Đoạn mã sau minh họa cách xóa hàng loạt và chèn hàng loạt theo cách giao dịch:

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

Lõi khung thực thể

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

Tóm tắt :

Xóa bộ sưu tập các thực thể đã cho khỏi bối cảnh bên dưới tập hợp với mỗi thực thể được đưa vào trạng thái Đã xóa để nó sẽ bị xóa khỏi cơ sở dữ liệu khi SaveChanges được gọi.

Nhận xét :

Lưu ý rằng nếu System.Data.Entity.Infr Hạ tầng.DbContextConfiguration.AutoDetectChangesEnables được đặt thành true (là mặc định), thì DetectChanges sẽ được gọi một lần trước khi xóa bất kỳ thực thể nào và sẽ không được gọi lại. Điều này có nghĩa là trong một số trường hợp, RemoveRange có thể hoạt động tốt hơn đáng kể so với việc gọi Xóa nhiều lần sẽ làm. Lưu ý rằng nếu có bất kỳ thực thể nào tồn tại trong ngữ cảnh ở trạng thái Đã thêm thì phương thức này sẽ khiến nó bị tách ra khỏi ngữ cảnh. Điều này là do một thực thể Đã thêm được giả sử không tồn tại trong cơ sở dữ liệu sao cho việc cố gắng xóa nó không có ý nghĩa.


1

Bạn có thể thực hiện các truy vấn sql trực tiếp như sau:

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

Để chọn, chúng tôi có thể sử dụng

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

Cho rằng EF không hỗ trợ đúng cách ánh xạ các điều kiện xóa, đây có lẽ là đặt cược tốt nhất của bạn để hoàn thành công việc.
Tony O'Hagan

1

Bạn cũng có thể sử dụng phương thức DeleteAllOnSubmit () bằng cách chuyển kết quả của bạn trong một danh sách chung thay vì theo var. Bằng cách này, foreach của bạn giảm xuống một dòng mã:

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

context.Widgets.DeleteAllOnSubmit(widgetList);

context.SubmitChanges();

Nó có thể vẫn sử dụng một vòng lặp nội bộ mặc dù.


3
Có vẻ như bạn đang hiểu nhầm a varlà gì .
Freedomn-m

1

Câu trả lời của Thanh làm việc tốt nhất cho tôi. Đã xóa tất cả hồ sơ của tôi trong một chuyến đi máy chủ. Tôi đã vật lộn với việc thực sự gọi phương thức mở rộng, vì vậy tôi nghĩ rằng tôi sẽ chia sẻ của tôi (EF 6):

Tôi đã thêm phương thức mở rộng vào một lớp trình trợ giúp trong dự án MVC của mình và thay đổi tên thành "RemoveWhere". Tôi tiêm dbContext vào bộ điều khiển của mình, nhưng bạn cũng có thể làm một 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);

Điều này tạo ra một tuyên bố xóa duy nhất cho nhóm.


0

EF 6. =>

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

0

Tốt : in EF6 => .RemoveRange()

Thí dụ:

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

14
Điều này khác với câu trả lời của Kyle như thế nào?

-1

Xem câu trả lời 'bit yêu thích của mã' hoạt động

Đây là cách tôi sử dụng nó:

     // 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
Câu trả lời của bạn khác với câu trả lời của người dùng1308743 như thế nào?
Serge Berezovskiy

Tôi chỉ đơn giản là chia sẻ một ví dụ làm việc. Bất cứ điều gì tôi có thể làm để trả lại sự giúp đỡ tôi nhận được ở đây.
Brian Quinn

-3

Trong EF 6.2, điều này hoạt động hoàn hảo, gửi xóa trực tiếp đến cơ sở dữ liệu mà không cần tải các thực thể đầu tiên:

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

Với một vị từ cố định, nó khá đơn giản:

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

Và nếu bạn cần một vị từ động, hãy xem LINQKit (gói Nuget có sẵn), một cái gì đó như thế này hoạt động tốt trong trường hợp của tôi:

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
Với EF 6.2 thô, điều này là không thể. Có lẽ bạn đang sử dụng Z.EntityFramework.Plushoặc một cái gì đó tương tự? ( entityframework.net/batch-delete )
Sammy S.

Đầu tiên là EF 6.2 thô và các công trình tìm thấy. Thứ hai là, như tôi đã đề cập, sử dụng LINQKit.
Vladimir

1
Hmm, tôi không thể tìm thấy phương pháp này. Bạn có thể kiểm tra lớp nào và không gian tên mà phương thức này cư trú không?
Sammy S.

Tôi thứ ba rằng ( Delete()phương pháp vốn không tồn tại).
Tổng hợp không có
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.