IEnumerable<>を使用するときにメモリオーバーフローを防ぐ方法とLinq-To-Sql?
-
06-07-2019 - |
質問
この質問は、私の以前の質問
に関連していますこれが私の現在のコードです
IEnumerable<Shape> Get()
{
while(//get implementation
yield return new Shape(//...
}
void Insert()
{
var actual = Get();
using (var db = new DataClassesDataContext())
{
db.Shapes.InsertAllOnSubmit(actual);
db.SubmitChanges();
}
}
IEnumerableが大きすぎるため、メモリオーバーフローが発生しています。どうすれば防ぐことができますか?
解決
<ではなく InsertOnSubmit を使用してみてくださいhref = "http://msdn.microsoft.com/en-us/library/bb763476(VS.100).aspx" rel = "nofollow noreferrer"> InsertAllOnSubmit 。そして、Erichが言ったように、適切な間隔でコミットします。
または、たとえば、 5、 Handcraftsman's または dtbのIEnumerableのIEnumerableを取得するためのソリューション。たとえば、dtbのチャンク:
var actual = Get();
using (var db = new DataClassesDataContext())
{
foreach(var batch in actual.Chunk(5))
{
db.Shapes.InsertAllOnSubmit(batch);
db.SubmitChanges();
}
}
他のヒント
1つのオプションは、複数のバッチに分割することです。 Shape
オブジェクトの一時バッファを作成し、それがいっぱいになるか、列挙子から実行されるまで繰り返し、 InsertBatchOnSubmit
を実行します。
次の拡張メソッドを使用して、入力を適切なサイズのサブセットに分割します
public static class IEnumerableExtensions
{
public static IEnumerable<List<T>> InSetsOf<T>(this IEnumerable<T> source, int max)
{
List<T> toReturn = new List<T>();
foreach(var item in source)
{
toReturn.Add(item);
if (toReturn.Count == max)
{
yield return toReturn;
toReturn = new List<T>();
}
}
if (toReturn.Any())
{
yield return toReturn;
}
}
}
その後、サブセットを永続化します
void Insert()
{
var actual = Get();
using (var db = new DataClassesDataContext())
{
foreach (var set in actual.InSetsOf(5))
{
db.Shapes.InsertAllOnSubmit(set);
db.SubmitChanges();
}
}
}
IEnumerableからアイテムのバッチを取得する適切な方法については、次を参照してください:
C#:文字列配列をN個のインスタンスN個のアイテムに分割する最もクリーンな方法
更新:いいえ、配列で動作します。後で時間があり、誰も何かを提供していない場合、それを書きます...
所属していません StackOverflow