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

  1. 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 ...;`
  2. Convert the multi-dimensional array to a single-dimensional array or a jagged array before the query.
  3. If the array is a constant, hoist all logic involving it outside the query body so the translator never visits the member access.
  4. 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

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


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)