Comment éviter un débordement de mémoire lors de l'utilisation d'un IEnumerable < T > et Linq-To-Sql?

StackOverflow https://stackoverflow.com/questions/1034429

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?

Était-ce utile?

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 ...

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top