dotnet/efcore · error · NotImplementedException
MemberAccess on multi-dimensional array
Error message
MemberAccess on multi-dimensional array
What it means
Thrown as NotImplementedException when a member access on `.Length` targets a multi-dimensional array (rank != 1). The translator special-cases `array.Length` for single-dimensional arrays by emitting an ArrayLength expression, but for multi-dimensional arrays it does not know how to represent the Length property (which on a multi-dim array returns the total element count, not something expression trees natively support) and throws.
Solutions
- Avoid referencing .Length on multi-dimensional arrays inside precompiled queries — capture the length as a separate int variable before the query and reference that: `int len = grid.Length; var query = ... len ...;`
- Convert the multi-dimensional array to a single-dimensional array or a jagged array before the query.
- If the array is a constant, hoist all logic involving it outside the query body so the translator never visits the member access.
- File an issue to support multi-dimensional array Length in the translator if this is important for your scenario.
Example fix
// before int[,] grid = LoadGrid(); var query = ctx.Cells.Where(c => grid.Length > 0 && c.Row < grid.GetLength(0)); // after — extract what you need before the query int[,] grid = LoadGrid(); int gridLength = grid.Length; int gridRows = grid.GetLength(0); var query = ctx.Cells.Where(c => gridLength > 0 && c.Row < gridRows);
Defensive patterns
Strategy: validation
Validate before calling
// Before precompiling, check for .Length access on multi-dimensional arrays
var multiDimLengthAccess = querySyntaxTree.DescendantNodes()
.OfType<MemberAccessExpressionSyntax>()
.Where(m =>
{
var exprType = semanticModel.GetTypeInfo(m.Expression).Type as IArrayTypeSymbol;
return m.Name.Identifier.Text == "Length" && exprType is { Rank: > 1 };
});
if (multiDimLengthAccess.Any())
ReportError(".Length on multi-dimensional arrays is not supported in precompiled queries"); Prevention
- Do not reference .Length or .GetLength() on multi-dimensional arrays inside precompiled query lambdas.
- Extract array dimensions (lengths) into separate int variables before the query.
- Convert multi-dimensional arrays to jagged arrays or flat arrays for use in precompiled queries.
- Keep array operations outside the query body.
When it happens
Trigger: A precompiled query accesses `.Length` on a multi-dimensional array variable: `int[,] grid = ...; var query = ctx.Data.Where(d => grid.Length > 0 && d.Value > 0);`. The translator detects the array type has rank != 1 and throws NotImplementedException.
Common situations: Capturing multi-dimensional arrays (matrices, grids, 2D lookup tables) as variables in a precompiled query and referencing their Length property inside the query lambda. Common in scientific computing, gaming, GIS, or image-processing domains embedded in EF query code.
Related errors
- ArrayCreation: multi-dimensional array
- Invocation over non-member access
- MemberAccess: couldn't find member
- MemberAccess: Couldn't find symbol for member
- Could not find symbol for method invocation
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/620dd4bbf0be2223.
Report an issue: GitHub.
Appendix: source
Thrown at src/EFCore.Design/Query/Internal/CSharpToLinqTranslator.cs:804
switch (memberInfo)
{
case Type nestedType:
return Constant(nestedType);
case null:
throw new InvalidOperationException($"MemberAccess: couldn't find member '{memberSymbol.Name}': {memberAccess}");
}
// Enum field constant
if (containingType.IsEnum)
{
return Constant(Enum.Parse(containingType, memberInfo.Name), containingType);
}
// array.Length
return expression.Type.IsArray && memberInfo.Name == "Length"
? expression.Type.GetArrayRank() != 1
? throw new NotImplementedException("MemberAccess on multi-dimensional array")
: (Expression)ArrayLength(expression)
: MakeMemberAccess(
expression is ConstantExpression { Value: Type } ? null : expression,
memberInfo);
}
/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public override Expression VisitObjectCreationExpression(ObjectCreationExpressionSyntax objectCreation)
{
if (_semanticModel.GetSymbolInfo(objectCreation).Symbol is not IMethodSymbol constructorSymbol)
{
throw new InvalidOperationException($"ObjectCreation: couldn't find IMethodSymbol for constructor: {objectCreation}");
}View on GitHub (pinned to 3a2006ef56)