【问题标题】:Breaking Change in EF Core 3.1 to 5 in stored procedure存储过程中 EF Core 3.1 到 5 的重大更改
【发布时间】:2021-07-10 21:56:16
【问题描述】:

我有一段代码在 .NET Core 3.1 (EF Core 3.1) 中完美运行,但我正在尝试迁移到 .NET 5 (EF Core 5) 但奇怪的是,我在运行它时遇到错误.NET 5.

这是错误:

System.InvalidOperationException: 'FromSqlRaw 或 FromSqlInterpolated 是用不可组合的 SQL 调用的,并且有一个查询在它上面进行组合。考虑在 FromSqlRaw 或 FromSqlInterpolated 方法之后调用 AsEnumerable 以在客户端执行组合。'

代码如下:

public async Task<IEnumerable<TeacherBookingDTO>> GetAllTeachers(string guid)
{
        try
        {
            IEnumerable<TeacherBookingDTO> teachers = await _context.TeacherBookings
            .FromSqlRaw("EXEC GetTeachersAndBookingsWithEveningId '{0}'", guid).Select(c => new TeacherBookingDTO {
                Id = c.Id,
                FirstName = c.FirstName,
                LastName = c.LastName,
                TotalBookings = c.TotalBookings
            })
            .ToListAsync();
            return teachers;
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }

        return null;
}

我尝试使用AsEnumerable,但我似乎无法让它工作。如果我删除返回 DTO 的尝试,即Select(...),它工作得很好。我当然可以在取回列表后进行转换,但我不知道为什么这不起作用。我已经搜索了重大更改,但看不到任何表明从 3.1 到 5 的任何更改会导致这种情况。它在 3.1 中被列为重大更改,但这是我的工作版本的 csproj TargetFramework:

<TargetFramework>netcoreapp3.1</TargetFramework>

奇怪的是,在 EF Core 5 中,我的 TeacherBookings 是在数据库中创建的,但不是在 EF Core 3.1 中。

这是来自DbContext的sn-p:

    public DbSet<YearGroup> YearGroups { get; set; }
    public DbSet<Comment> Comments { get; set; }

    public virtual DbSet<TeacherBooking> TeacherBookings { get; set; }
    public virtual DbSet<StudentBooking> StudentBookings { get; set; }

非常感谢任何帮助。

【问题讨论】:

    标签: c# entity-framework .net-core entity-framework-core .net-5


    【解决方案1】:

    也尝试在存储过程之后添加 ToList

       IEnumerable<TeacherBookingDTO> teachers = (
    await _context.TeacherBookings
     .FromSqlRaw("EXEC GetTeachersAndBookingsWithEveningId '{0}'", guid).ToListAsync()
    )
    .Select(c => new TeacherBookingDTO {
                    Id = c.Id,
                    FirstName = c.FirstName,
                    LastName = c.LastName,
                    TotalBookings = c.TotalBookings
                })
                .ToList();
    

    FromSqlRaw 这样工作。它总是返回 IEnumerable。因此,例如,如果您只需要第一条记录并且您的存储过程将只返回这条记录,那么无论如何您都需要这样的代码。首先,您必须将数据作为记录列表加载,并且只有在此之后才尝试对此进行处理

    var teacher = (
    await _context.TeacherBookings
     .FromSqlRaw("EXEC GetTeachersAndBookingsWithEveningId '{0}'", guid).ToListAsync()
    )
    .Select(c => new TeacherBookingDTO {
                    Id = c.Id,
                    FirstName = c.FirstName,
                    LastName = c.LastName,
                    TotalBookings = c.TotalBookings
                })
                .FirstOrDefault();
    

    例如,ExecuteSqlRaw 总是只返回一个属性,所以一开始不需要在特殊模型中加载它。

    【讨论】:

    • 谢谢。我已经尝试了您的建议并且它有效,但我不明白为什么原始代码在 EF5 中不起作用。在 ToList 上做 ToList 似乎很奇怪!
    猜你喜欢
    • 2020-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-27
    • 1970-01-01
    • 2021-11-05
    • 2020-07-19
    相关资源
    最近更新 更多