Sam*_*tar 39 entity-framework entity-framework-6
我正在使用Entity Framework 6.
我有一个表格,里面有一个名为Tests的测试信息.我通过首先获取测试列表,为每个测试执行删除然后提交来删除此表中的行.
var testList = _testService.GetTests(1, userId).ToList();
testList.ForEach(_obj => _uow.Tests.Delete(_obj));
_uow.Commit();
Run Code Online (Sandbox Code Playgroud)
我有另一个表格,其中包含问题信息.我想做同样的事情,但这张表中有超过1000行.如果我将它们全部列出然后执行1,000次删除将不会非常有效.
这种问题的删除并不经常发生.有没有人建议如何做到这一点.我应该做1000次删除吗?使用EF做这种事情是正常的吗?
Tom*_*mmy 88
据我所知,EF 6在你的DbContext上引入了.RemoveRange()选项.简而言之,您可以执行以下操作:
var db = new MyDbContext();
var itemsToDelete = db.MyTable.Where(x=>!x.active);
db.MyTable.RemoveRange(itemsToDelete);
db.SaveChanges();
Run Code Online (Sandbox Code Playgroud)
因此foreach,您可以使用这种新的扩展方法,而不必执行任何类型的操作.使用Unit Of Work上下文,您可以Delete使用IEnumerable(?*)而不是Test像当前方法那样的单个对象来重载您的方法.这个新的重载应该调用RemoveRange()DbContext上的函数.
?* - 这取决于什么GetTests()回报,但我认为IEnumerable<>涵盖了一个IList<>和一个IQueryable<>
编辑
几条评论.首先,我不会.ToList()在发出之前打电话,RemoveRange因为您不想实际获取服务项目.这应该有助于减少一些性能时间.其次,你是对的,你还会发出1000个删除语句.但是,性能提升来自于不在EF中为您要删除的每个项目调用ChangeTracker DbSet.来自MSDN杂志:
AddRange和RemoveRange如前所述,AddRange和RemoveRange是社区成员Zorrilla的贡献.每个方法都将其参数作为单个实体类型的可枚举.在共享DbTransactions部分的第一个代码示例中,当我传入Casino实例数组时,我使用了AddRange:
context.Casinos.AddRange(new [] {casino1,casino2}); 这些方法的执行速度比一次添加或删除单个对象要快得多,因为默认情况下,Entity Framework会在每个Add和Remove方法中调用DetectChanges.使用Range方法,您可以处理多个对象,而DetectChanges只被调用一次,从而显着提高性能.我已经使用5个,50个,500个,5,000个甚至50,000个对象测试了这个,至少在我的场景中,对阵列的大小没有限制 - 而且它的速度非常快!请记住,此改进仅与获取上下文以对象操作相关,并且与SaveChanges无关.调用SaveChanges仍然一次只执行一个数据库命令.因此,虽然您可以快速将50,000个对象添加到上下文中,但在调用SaveChanges时仍然可以单独执行50,000个插入命令 - 可能不是您想要在实际系统中执行的操作.
另一方面,长期以来一直在讨论实现对批量操作的支持,而不需要EF(bit.ly/16tMHw4)跟踪对象,以及批量操作以便在一次调用数据库时一起发送多个命令(bit.ly/PegT17).这两个功能都没有进入最初的EF6版本,但两者都很重要,并且将在未来版本中发布.
如果您确实只想发出单个数据库命令,那么使用原始SQL语句的存储过程将是一种方法,因为EntityFramework不支持批量事务.但是,与调用foreach循环相比,使用RemoveRange和AddRange项目(特别是如你所说的那样,不常见)将节省大量时间Remove().
Ane*_*lou 12
内置实体框架.RemoveRange() 方法,仍然在内存中获取条目,并发出X删除所有循环.
如果您不想编写任何SQL for Deletion,尤其是在选择要删除的实体很复杂时
Entity Framework Plus Library提供批量删除更新方法,只发出一个命令.
// Deleting
context.Users
.Where(u => u.FirstName == "firstname")
.Delete();
Run Code Online (Sandbox Code Playgroud)
实体框架的当前限制是,为了更新或删除实体,您必须首先将其检索到内存中.现在在大多数情况下,这很好.然而,有一些senerios性能会受到影响.此外,对于单个删除,必须先检索该对象,然后才能删除该对象,从而需要对数据库进行两次调用.批量更新和删除消除了在修改实体之前检索和加载实体的需要.
我使用 EF6 和 Sql Server Profiler 做了一些测试
使用 .RemoveRange()
它首先获取要从数据库中删除的所有记录
exec sp_executesql N'SELECT [Extent1].[Id] AS [Id], [Extent1].[IdOrder] AS [IdOrder], [Extent1].[Name] AS [Name], [Extent1].[Partita] AS [ Partita], FROM [dbo].[MyTable] AS [Extent1] WHERE [Extent1].[IdOrder] = @p__linq__0',N'@p__linq__0 varchar(8000)',@p__linq__0='0cb41f32-7ccb-426a-a159- b85a4ff64c29'
然后它向数据库发出 N 删除命令
exec sp_executesql N'DELETE [dbo].[MyTable] WHERE ([Id] = @0)',N'@0 varchar(50)',@0='ffea29aa-8ba5-4ac9-871b-3f5979180006'
X 1000 次
这也发生在使用和 IQueriable
使用实体框架扩展库
它只向数据库发出一个命令
exec sp_executesql N'DELETE [dbo].[MyTable] FROM [dbo].[MyTable] AS j0 INNER JOIN (SELECT 1 AS [C1], [Extent1].[Id] AS [Id] FROM [dbo].[MyTable] ] AS [Extent1] WHERE [Extent1].[IdOrder] = @p__linq__0) AS j1 ON (j0.[Id] = j1.[Id])',N'@p__linq__0 nvarchar(36)',@p__linq__0=N' 0cb41f32-7ccb-426a-a159-b85a4ff64c29'
| 归档时间: |
|
| 查看次数: |
39250 次 |
| 最近记录: |