{"record":{"id":"97b6c82616eeb412","repo":"dotnet/efcore","slug":"this-enumerator-cannot-be-reset-97b6c8","errorCode":null,"errorMessage":"This enumerator cannot be reset.","messagePattern":"This enumerator cannot be reset\\.","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Relational/Query/Internal/FromSqlQueryingEnumerable.cs","lineNumber":296,"sourceCode":"            enumerator._indexMap = BuildIndexMap(enumerator._columnNames, enumerator._dataReader.DbDataReader);\n\n            enumerator._relationalQueryContext.InitializeStateManager(enumerator._standAloneStateManager);\n\n            return false;\n        }\n\n        public void Dispose()\n        {\n            if (_dataReader is not null)\n            {\n                _relationalQueryContext.Connection.ReturnCommand(_relationalCommand!);\n                _dataReader?.Dispose();\n                _dataReader = null;\n            }\n        }\n\n        public void Reset()\n            => throw new NotSupportedException(CoreStrings.EnumerableResetNotSupported);\n    }\n\n    private sealed class AsyncEnumerator : IAsyncEnumerator<T>\n    {\n        private readonly RelationalQueryContext _relationalQueryContext;\n        private readonly RelationalCommandResolver _relationalCommandResolver;\n        private readonly IReadOnlyList<ReaderColumn?>? _readerColumns;\n        private readonly IReadOnlyList<string> _columnNames;\n        private readonly Func<QueryContext, DbDataReader, int[], T> _shaper;\n        private readonly Type _contextType;\n        private readonly IDiagnosticsLogger<DbLoggerCategory.Query> _queryLogger;\n        private readonly bool _standAloneStateManager;\n        private readonly bool _detailedErrorsEnabled;\n        private readonly IConcurrencyDetector? _concurrencyDetector;\n        private readonly IExceptionDetector _exceptionDetector;\n\n        private IRelationalCommand? _relationalCommand;\n        private RelationalDataReader? _dataReader;","sourceCodeStart":278,"sourceCodeEnd":314,"githubUrl":"https://github.com/dotnet/efcore/blob/dbf9771522148d61a2467854921bd5dc6f6e6916/src/EFCore.Relational/Query/Internal/FromSqlQueryingEnumerable.cs#L278-L314","documentation":"Thrown from Enumerator.Reset() on the FromSql query enumerable (FromSqlQueryingEnumerable.cs:296). EF's relational query enumerators wrap a forward-only DbDataReader that streams results from the database; once consumed, the reader cannot be rewound. IEnumerator.Reset is therefore explicitly unsupported and throws NotSupportedException. This is by design: EF enumerables are single-pass and do not buffer the result set.","triggerScenarios":"Code that calls .Reset() on an IEnumerator obtained from an EF query (e.g. via a helper, a LINQ operator implementation, or a library that assumes Reset works). Also triggered by enumerating the same query twice via the same enumerator instance, or by frameworks that call Reset during custom aggregation/caching.","commonSituations":"Porting code that used LINQ-to-Objects (where Reset is supported) to EF; third-party libraries that buffer/re-iterate enumerators; misuse of GetAsyncEnumerator()/GetEnumerator() directly instead of re-running the query.","solutions":["Do not call Reset(); instead, materialize results once with ToList()/ToListAsync() and re-iterate the in-memory list.","Re-execute the query from the IQueryable to get a fresh enumerator (this re-issues the SQL).","If you need multiple passes, call AsEnumerable() (or AsAsyncEnumerable()) after ToList to move to an in-memory sequence that supports Reset.","Replace manual enumerator usage with foreach / await foreach."],"exampleFix":"// before - calling Reset on an EF enumerator\nvar enumerator = context.Blogs.FromSqlRaw(\"SELECT * FROM Blogs\").GetEnumerator();\nenumerator.MoveNext();\nenumerator.Reset(); // throws NotSupportedException\n\n// after - buffer once, iterate the list freely\nvar blogs = context.Blogs.FromSqlRaw(\"SELECT * FROM Blogs\").ToList();\nvar enumerator = blogs.GetEnumerator(); // List<T>.Enumerator supports Reset-free iteration\n// or just foreach over the list as many times as needed","handlingStrategy":"validation","validationCode":"// Never call Reset() on an EF enumerable. Materialize once and iterate the list.\nvar materialized = ctx.Set<T>().FromSqlRaw(sql).ToList(); // List<T> is freely re-iterable","typeGuard":"// Detect resettable vs single-pass enumerators before calling Reset.\nstatic bool IsResettable<T>(IEnumerable<T> source) => source is IList<T> or Array or ICollection<T>;\n// Usage: if (IsResettable(seq)) e.Reset(); else re-enumerate.","tryCatchPattern":"try { e.Reset(); }\ncatch (NotSupportedException) {\n    // EF query enumerators cannot be reset; materialize and reuse instead.\n    var list = query.ToList();\n}","preventionTips":["Avoid calling IEnumerator.Reset() on any EF query; prefer foreach.","Materialize queries with ToList()/ToListAsync() when you need multiple passes.","Do not hand EF enumerators to libraries that call Reset; pass the buffered list.","Document that EF enumerables are single-pass forward-only."],"tags":["ef-core","enumerator","reset","datareader","query"],"analyzedSha":"dbf9771522148d61a2467854921bd5dc6f6e6916","analyzedAt":"2026-08-06T20:46:03.226Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}