使用LINQPad将数据插入到SQL CE数据库中,Linq-to-sql随着时间的推移变得越来越慢,我能做些什么呢?

我在磁盘上有一个SQL CE 4.0数据库,以及一个我想用来填充该数据库的LINQPad程序。

我正在使用内置的(到LINQPad)linq2sql系统。 我注意到随着时间的推移,插入一批行所花费的时间会花费越来越多的时间,最终看起来程序已经慢慢爬行了。

是否有某种缓存或类似缓慢的缓存? 如果有的话,我可以做些什么来避免这种减速?

这是我用来测试它的简单测试表:

CREATE TABLE dummy ( id int not null primary key identity (1, 1), value nvarchar(20) not null ) 

和我的测试程序:

 void Main() { for (int iteration = 1; iteration <= 1000; iteration++) { Stopwatch sw = Stopwatch.StartNew(); for (int row = 0; row < 100; row++) dummy.InsertOnSubmit(new dummy { value = "row#" + row }); var create = sw.ElapsedMilliseconds; SubmitChanges(); sw.Stop(); var total = sw.ElapsedMilliseconds; Debug.WriteLine("iteration " + iteration + ", create=" + create + ", total=" + total); } } 

这里的示例输出:

 iteration 1, create=1, total=52 iteration 2, create=0, total=41 iteration 3, create=0, total=53 iteration 4, create=0, total=45 ... iteration 86, create=0, total=181 iteration 87, create=0, total=218 iteration 88, create=0, total=172 iteration 89, create=4, total=192 ... iteration 167, create=0, total=387 iteration 168, create=0, total=427 iteration 169, create=0, total=496 iteration 170, create=0, total=425 

如您所见,调用SubmitChanges花费的时间越来越长,但每次迭代我都会插入相同数量的实体。

请注意,我完全清楚我不会像批量插入那样获得速度,但是如果可能的话,我仍然希望避免这种速度减慢。

另请注意,如果我现在重新运行程序,数据库中已有很多行,则时间再次开始:

 iteration 1, create=1, total=51 iteration 2, create=0, total=50 iteration 3, create=0, total=45 iteration 4, create=0, total=45 

所以在我看来,有些东西在记忆中不断增长。

有没有什么我可以关闭,重置,转储,等等,以解决这个问题,除了定期停止程序并重新启动它(这是我真正做的事情,但我想避免它) 。

听起来你想从LINQPad中将数据批量复制到SQL Server。 这是我用来做的一种方法:

 void BCP (IEnumerable rows) { if (rows.Count() == 0) return; var dt = new DataTable (); var metaTable = _db.Mapping.GetTable (typeof (TRow)); var columns = metaTable.RowType.DataMembers.Where (dm => dm.Association == null); var transformers = new List>(); foreach (var columnX in columns) { var column = columnX; dt.Columns.Add (column.Name, L2sToDataTable (column.Type)); transformers.Add (row => L2sToDataTable (row.GetType().GetField (column.Name).GetValue (row))); } foreach (var row in rows) dt.Rows.Add (transformers.Select (t => t (row)).ToArray()); _db.Connection.Open(); Console.Write ("Bulk copying " + metaTable.TableName + "... "); var bcp = new SqlBulkCopy ((SqlConnection)_db.Connection) { DestinationTableName = metaTable.TableName, BulkCopyTimeout = 300 }; bcp.BatchSize = 20; bcp.NotifyAfter = 20; bcp.SqlRowsCopied += (sender, args) => Console.Write (args.RowsCopied + " rows... "); bcp.WriteToServer (dt); _db.Connection.Close(); Console.WriteLine ("Done"); } Type L2sToDataTable (Type l2sType) { if (l2sType == typeof (Binary)) return typeof (byte[]); if (l2sType.IsGenericType && l2sType.GetGenericTypeDefinition() == typeof (Nullable<>)) return l2sType.GetGenericArguments()[0]; return l2sType; } object L2sToDataTable (object l2sValue) { if (l2sValue == null) return DBNull.Value; if (l2sValue is Binary) return ((Binary) l2sValue).ToArray(); return l2sValue; } 

这避免了对象关系映射器(如LINQ-to-SQL)的缓存内存开销,同时利用后者的元数据。