我有一个使用EF 6.1的数据库第一个模型。
我需要大量导入数据。在Mysql中,将整个流拆分为500个元素和AddRange
的较小集合,从而产生合理的插入性能(我还通过使代码并行并对线程数进行基准测试来调整代码)。
在SQL Server上运行时,相同的代码会产生可怕的性能。 SQL Server探查器显示EF尝试将每个实体作为单独的INSERT插入,但不使用普通的INSERT
,而是依赖于sp_executesql
示例:
public int Save(IList<BaseEntity> entities)
{
using (var dataContext = GetDataContext())
{
using (var tx = dataContext.Database.BeginTransaction())
{
dataContext.Configuration.AutoDetectChangesEnabled = false;
dataContext.Configuration.ValidateOnSaveEnabled = false;
dataContext.Configuration.LazyLoadingEnabled = false;
var sa = entities.OfType<A>();
var sd = entities.OfType<D>();
var se = entities.OfType<E>();
var sf = entities.OfType<F>();
var sg = entities.OfType<G>();
var sh = entities.OfType<H>();
dataContext.sezione_a.AddRange(sa);
dataContext.sezione_d.AddRange(sd);
dataContext.sezione_e.AddRange(se);
dataContext.sezione_f.AddRange(sf);
dataContext.sezione_g.AddRange(sg);
dataContext.sezione_h.AddRange(sh);
int ret = dataContext.SaveChanges();
tx.Commit();
return ret
}
}
}
这是因为我的列表包含多个实体的混合,但整个列表最多可以计数500个。更多线程同时调用此方法。
当我运行探查器时,我可以看到
exec sp_executesql N'INSERT [dbo].[sezione_a]([A01], [A01a], [A01b], [A02], [A03], [A11], [A12], [A12a], [A12b], [A12c], [A21], [A22], [A23], [A24], [A25], [A31], [A31a], [A31b], [A32], [A33], [A33a], [A33b], [A33c], [A34], [A41], [A42], [A43], [A51], [A52], [A53], [A54], [A54a], [A54b], [A54c], [B11], [B12], [B13], [B14], [B15], [Z0], [progA], [utente])
VALUES (@0, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @11, @12, @13, @14, @15, @16, @17, @18, @19, @20, @21, @22, @23, @24, @25, @26, @27, @28, @29, @30, @31, @32, @33, @34, @35, @36, @37, @38, @39, @40, @41)
',N'@0 varchar(13),@1 varchar(2),@2 varchar(11),@3 varchar(1),@4 varchar(20),@5 varchar(6),@6 varchar(38),@7 varchar(6),@8 varchar(30),@9 varchar(2),@10 varchar(8),@11 varchar(1),@12 varchar(1),@13 varchar(4),@14 varchar(2),@15 varchar(13),@16 varchar(2),@17 varchar(11),@18 varchar(3),@19 varchar(38),@20 varchar(6),@21 varchar(30),@22 varchar(2),@23 varchar(50),@24 varchar(25),@25 varchar(1),@26 varchar(1),@27 varchar(8),@28 varchar(2),@29 varchar(12),@30 varchar(29),@31 varchar(1),@32 varchar(8),@33 varchar(20),@34 varchar(1),@35 varchar(3),@36 varchar(1),@37 decimal(18,2),@38 decimal(18,2),@39 varchar(69),@40 bigint,@41 int',@0='0907084500011',@1='09',@2='07084500011',@3='1',@4='20110209100276666600',[...]
每个记录都会重复此操作。
我已经检查了其他批量插入策略,但由于我的应用程序需要可以在MS SQL和Mysql中移植,所以我不能依赖依赖于SqlBulkCopy的其他库。我的意思是我想使用相同的代码。
Mysql看起来像是为6个表中的每个表压缩插入到单个INSERT
中。 SQL Server看起来没有。
我还检查了我的edmx模型,在阅读了varchar
与nvarchar
问题之后,我将所有列标准化为varchar
和Unicode="false"
直接进入xml。 / p>
但那没用。
我可以做什么让EF将INSERT
纳入单一陈述并获得不错的表现? 500行的200秒是不可接受的。
答案 0 :(得分:1)
Entity Framework使用ADO.NET,当使用paramterized SQL时,总是使用sp_executesql - 为什么这会让你担心? EF 6不支持批处理INSERT,它在EF Core中可用。为了快速,批量更新使用带有表值参数的ADO.NET和SqlClient SqlBulkCopy API