Comment éviter un débordement de mémoire lors de l'utilisation d'un IEnumerable < T > et Linq-To-Sql?
-
06-07-2019 - |
Question
Cette question concerne la une de mes précédentes questions
.C'est mon code actuel
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();
}
}
Je reçois un dépassement de mémoire, car le IEnumerable est trop gros. Comment puis-je l'empêcher?
La solution
Essayez d’utiliser InsertOnSubmit plutôt que < a href = "http://msdn.microsoft.com/en-us/library/bb763476(VS.100).aspx" rel = "nofollow noreferrer"> InsertAllOnSubmit . Et puis commettez à intervalles appropriés, comme l’a dit Erich.
Ou, si vous souhaitez le faire par lots, par exemple. 5, essayez Artisan ou solutions dtb pour l'obtention d'IEnumerable de IEnumerable. Par exemple, avec le bloc de dtb:
var actual = Get();
using (var db = new DataClassesDataContext())
{
foreach(var batch in actual.Chunk(5))
{
db.Shapes.InsertAllOnSubmit(batch);
db.SubmitChanges();
}
}
Autres conseils
Une option consiste à le diviser en plusieurs lots. Créez un tampon temporaire d'objets Shape
, effectuez une itération jusqu'à ce que vous le remplissiez ou sortiez de l'énumérateur, puis effectuez un InsertBatchOnSubmit
.
Utilisez la méthode d'extension suivante pour diviser l'entrée en sous-ensembles de taille appropriée
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;
}
}
}
puis persistez les sous-ensembles
void Insert()
{
var actual = Get();
using (var db = new DataClassesDataContext())
{
foreach (var set in actual.InSetsOf(5))
{
db.Shapes.InsertAllOnSubmit(set);
db.SubmitChanges();
}
}
}
Vous pouvez également trouver Cet article MSDN sur InsertOnSubmit () vs InsertAllOnSubmit () peut être utile.
Pour obtenir un moyen astucieux d’obtenir des lots d’articles d’un IEnumerable, consultez ceci:
C #: le moyen le plus propre de diviser un tableau de chaînes en N instances de N éléments de long
Mise à jour: rien de bon, cela fonctionne sur les tableaux. Si j’ai un peu de temps après et que personne d’autre n’a fourni quelque chose, je vais le noter ...