可以在方法中执行EFCORE子查询(以提高可读性)

发布于 2025-01-20 20:12:23 字数 2532 浏览 1 评论 0原文

我试图使我的代码更加清洁,更容易阅读,但是我得到了EFCORE的例外(它们表明这可能是一个限制),只是想看看是否有人可以提供帮助。

我正在使用.NET3.1和EFCORE 3.1。

原始代码工作:

    public Response GetAll(long myId, DataSourceLoadOptions loadOptions)
    {
        var dbContext = ContextFactory.GetContext<IMyContext>();
        var query = dbContext.Table1.Where(_ => _.Id == myId).Select(ent1 => new
        {
            Id = ent1.Id,
            State = ent1.State,
            MatCode = ent1.Mat.Code,
            AmountToFulfill = ent1.AmountRequested,
            AmountReserved = dbContext.Table2.Where(matres => matres.Ent1Id == ent1.Id && matres.State == MaterialReservationState.Active).Select(_ => _.AmountReserved).Sum(),
            LastChangeTime = ent1.ChangeTime,
        });

        return query.ToList();
    }

不工作代码:

    public Response GetAll2(long myId, DataSourceLoadOptions loadOptions)
    {
        var dbContext = ContextFactory.GetContext<IMyContext>();
        var query = dbContext.Table1.Where(_ => _.Id == myId).Select(ent1 => new
        {
            Id = ent1.Id,
            State = ent1.State,
            MatCode = ent1.Mat.Code,
            AmountToFulfill = ent1.AmountRequested,
            AmountReserved = GetReservedAmount(dbContext, ent1).Sum(),
            LastChangeTime = ent1.ChangeTime,
        });

        return query.ToList();
    }

    private static IQueryable<int> GetReservedAmount(IMyContext dbContext, IEntity1 ent1)
    {
        return dbContext.Table2
            .Where(matres => matres.Ent1Id == ent1.Id && matres.State == MaterialReservationState.Active)
            .Select(_ => _.AmountReserved);
    }

异常:

[21:26:28.1605 ERR]在执行请求时发生了一个未手持异常。 {endId = {id = 1,name =“ unhandledException”},sourcecontext =“ microsoft.aspnetcore.diagnostics.diagnostics.diageptionhandlermiddleware”,requestId =“ 0hxxxxxxa83m7jb:0000000001 48248xxxxxxx5b806.1.eee74277_“,traceId =” 5e3cde39-4824xxxxxx' system.invalidoperationException:linq expression'className.getAll2的处理( dbContext:__dbContext_1, OP :( NavigationTree Expression 价值:( EntityReference:Entity1) 表达式:o.outer)) 。这可能表明EF核心中的错误或限制。参见 https://go.microsoft.com/fosoft.com/fwlink/?有关更多详细信息。 在Microsoft.entityframeworkcore.query.internal.navigation ExpandingExpressionVisitor.visitmethodcall(MethodCallexPress MethodCallexPression) ........

I am trying to make my code a little bit cleaner and easier to read but I am getting an efcore exception (they indicate this might be a limitation), just wanted to see if anyone can help.

I am using .net3.1 and efcore also 3.1.

Original code working:

    public Response GetAll(long myId, DataSourceLoadOptions loadOptions)
    {
        var dbContext = ContextFactory.GetContext<IMyContext>();
        var query = dbContext.Table1.Where(_ => _.Id == myId).Select(ent1 => new
        {
            Id = ent1.Id,
            State = ent1.State,
            MatCode = ent1.Mat.Code,
            AmountToFulfill = ent1.AmountRequested,
            AmountReserved = dbContext.Table2.Where(matres => matres.Ent1Id == ent1.Id && matres.State == MaterialReservationState.Active).Select(_ => _.AmountReserved).Sum(),
            LastChangeTime = ent1.ChangeTime,
        });

        return query.ToList();
    }

Not working code:

    public Response GetAll2(long myId, DataSourceLoadOptions loadOptions)
    {
        var dbContext = ContextFactory.GetContext<IMyContext>();
        var query = dbContext.Table1.Where(_ => _.Id == myId).Select(ent1 => new
        {
            Id = ent1.Id,
            State = ent1.State,
            MatCode = ent1.Mat.Code,
            AmountToFulfill = ent1.AmountRequested,
            AmountReserved = GetReservedAmount(dbContext, ent1).Sum(),
            LastChangeTime = ent1.ChangeTime,
        });

        return query.ToList();
    }

    private static IQueryable<int> GetReservedAmount(IMyContext dbContext, IEntity1 ent1)
    {
        return dbContext.Table2
            .Where(matres => matres.Ent1Id == ent1.Id && matres.State == MaterialReservationState.Active)
            .Select(_ => _.AmountReserved);
    }

Exception:

[21:26:28.1605 ERR] An unhandled exception has occurred while executing the request. {EventId={Id=1, Name="UnhandledException"}, SourceContext="Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware", RequestId="0HxxxxxA83M7JB:00000001", RequestPath="/xxxxxxxxxx/2", SpanId="|5exxx39-48248xxxxx5b806.1.eee74277_", TraceId="5e3cde39-4824xxxxx", ParentId="|5e3cxxde39-48248xxxxxa25b806.1.", ConnectionId="0xxxxxx", ThreadId=11}
System.InvalidOperationException: Processing of the LINQ expression 'ClassName.GetAll2(
dbContext: __dbContext_1,
op: (NavigationTreeExpression
Value: (EntityReference: Entity1)
Expression: o.Outer))
.Sum()' by 'NavigationExpandingExpressionVisitor' failed. This may indicate either a bug or a limitation in EF Core. See https://go.microsoft.com/fwlink/?linkid=2101433 for more detailed information.
at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
.......

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

似狗非友 2025-01-27 20:12:23

您已经获得的错误使您完全说明那里有什么问题:

linq Expression'ClassName.getAll2(dbContext:__dbContext_1,OP :( navigationTreeTreeExpression值:( EntityReference:entityReference:entity1)表达式:o.outer1).sum(o.outer)).sum()

如果您转到提供的链接( https://go.microsoft.com/fwlink/? = 2101433 )然后您可以阅读:

ef核心支持顶级投影中的部分客户评估(从本质上讲,是select()的最后一个呼叫)。如果查询中的顶级投影无法转换为服务器,EF Core将从服务器中获取任何必需的数据,并评估客户端上查询的剩余部分。如果EF核心检测到一个表达式,则在无法翻译到服务器的顶级投影以外的任何地方,然后引发运行时异常。

您的方法

private static IQueryable<int> GetReservedAmount(IMyContext dbContext, IEntity1 ent1)
{
    return dbContext.Table2
        .Where(matres => matres.Ent1Id == ent1.Id && matres.State == MaterialReservationState.Active)
        .Select(_ => _.AmountReserved);
}

不能转换为TSQL查询语法。

就是这样,从EF Core版本3.0客户端方法无法转换为TSQL。

The error you've got give you complete explanation what's wrong there:

Processing of the LINQ expression 'ClassName.GetAll2( dbContext: __dbContext_1, op: (NavigationTreeExpression Value: (EntityReference: Entity1) Expression: o.Outer)) .Sum()' by 'NavigationExpandingExpressionVisitor' failed.

If you go to provided link (https://go.microsoft.com/fwlink/?linkid=2101433) then you can read that:

EF Core supports partial client evaluation in the top-level projection (essentially, the last call to Select()). If the top-level projection in the query can't be translated to the server, EF Core will fetch any required data from the server and evaluate remaining parts of the query on the client. If EF Core detects an expression, in any place other than the top-level projection, which can't be translated to the server, then it throws a runtime exception.

Your method

private static IQueryable<int> GetReservedAmount(IMyContext dbContext, IEntity1 ent1)
{
    return dbContext.Table2
        .Where(matres => matres.Ent1Id == ent1.Id && matres.State == MaterialReservationState.Active)
        .Select(_ => _.AmountReserved);
}

can't be translated to TSQL query syntax.

That's it, from EF Core version 3.0 client methods can't be translated to TSQL.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文