获得“下一个价值"对于使用 EF Core 3.1 的 SQL Server 序列 - 不可能?

我正在编写一个新的 ASP.NET Core Web API,我的要求之一是能够利用 EF Core 3.1 来获取在我的 SQL Server 中定义的序列的下一个值作为我需要存储的记录的 ID.

I'm writing a new ASP.NET Core Web API, and one of my requirements is to be able to leverage EF Core 3.1 to grab the next value of a sequence defined in my SQL Server as the ID for a record I need to store.

我正在努力寻找一种方法来做到这一点 - 在 EF 6.x 中,我直接在 DbContext 后代上使用了一种方法,如下所示:

I'm struggling to find a way to do this - in EF 6.x, I used a method directly on the DbContext descendant like this:

public int GetNextSequenceValue()
{
    var rawQuery = Database.SqlQuery<int>("SELECT NEXT VALUE FOR dbo.TestSequence;");
    var task = rawQuery.SingleAsync();
    int nextVal = task.Result;

    return nextVal;
}

对于高达 2.1 的 EF Core,我本来可以使用 Database.ExecuteSqlCommand() 来运行 SQL 代码段并返回结果.但似乎在 EF Core 3.x 中,我不走运....

and for EF Core up to 2.1, I would have been able to use Database.ExecuteSqlCommand() to run a SQL snippet and get back results. But it seems, in EF Core 3.x, I'm out of luck....

我知道 .FromSqlRaw().FromSqlInterpolated 方法在 DbSet 上 - 但因为我只需要返回下一个序列的值(INT),它不会飞.而且我也知道这些方法也存在于 context.Database 级别,看起来它与我在 EF 6.x 中的非常接近 - 但在这里,这些方法将只 返回受影响的行数 - 我还没有找到从 SEQUENCE 发回新值的方法.

I know there are the .FromSqlRaw() and .FromSqlInterpolated methods on the DbSet - but since I only need to return the next value of a sequence (an INT), that's not going to fly. And I also know these methods also exist on the context.Database level which looks like it would be really close to what I had in EF 6.x - but here, those methods will only return the number of rows affected - I haven't found a way to send back the new value from the SEQUENCE.

在 EF Core 3.x 中真的可以这样,我实际上必须求助于古老的 ADO.NET 代码来获取该值吗??是否有真的无法执行任意 SQL 代码段并从上下文中获取一些结果??

Can it really be that in EF Core 3.x, I have to actually resort back to way-old ADO.NET code to fetch that value?? Is there REALLY no way to execute an arbitrary SQL snippet and get back some results from the context??

推荐答案

如果你想运行一个任意的 TSQL 批处理并返回一个标量值,你可以这样做:

If you want to run an arbitrary TSQL batch and return a scalar value, you can do it like this:

var p = new SqlParameter("@result", System.Data.SqlDbType.Int);
p.Direction = System.Data.ParameterDirection.Output;
context.Database.ExecuteSqlRaw("set @result = next value for some_seq", p);
var nextVal = (int)p.Value;

相关文章