如何在EF Core 3.0中使用FromSqlInterpolated对多个参数执行存储过程?

时间:2019-12-03 06:53:00

标签: asp.net-core stored-procedures .net-core entity-framework-core ef-core-3.0

我在Sql Server 2017中有一个存储过程,该过程采用三个参数。

CREATE PROCEDURE UpdateRestaurantInformation
@restaurantId nvarchar(max),
@restaurantName nvarchar(max),
@locationId int
AS
BEGIN
    UPDATE Restaurants
    SET RestaurantName = @restaurantName, LocationId = @locationId
    WHERE RestaurantId = @restaurantId;

    SELECT * FROM Restaurants WHERE RestaurantId = @restaurantId;
END

当我尝试使用下面的代码片段执行此存储过程时,它正常工作

   SqlParameter param1 = new SqlParameter("@p0",restaurant.RestaurantId);
   SqlParameter param2 = new SqlParameter("@p1", restaurant.RestaurantName);
   SqlParameter param3 = new SqlParameter("@p2", restaurant.Location.LocationId);

     var res = _context.Restaurants
    .FromSqlRaw("UpdateRestaurantInformation @p0,@p1,@p2", param1, param2, param3)
    .ToList();

但是当我尝试使用FromSqlInterpolated时,如下所示:

var res = await _context.Restaurants
   .FromSqlInterpolated(
   $"UpdateRestaurantInformation {restaurant.RestaurantId}, {restaurant.RestaurantName}, {restaurant.Location.LocationId}")
   .SingleAsync();

抛出此异常:

  

SqlException:“ @ p0”附近的语法不正确。   Microsoft.Data.SqlClient.SqlCommand + <> c.b__164_0(任务   结果)

我在这里误会什么?拜托,有人帮我。

2 个答案:

答案 0 :(得分:1)

您可以通过以下文章了解如何在ef core中使用sql命令:

https://www.learnentityframeworkcore.com/raw-sql#stored-procedures https://www.learnentityframeworkcore.com/raw-sql#database.executesqlcommand

随着efcore更新。您不需要在新的efcore api中构建SqlParameter。

ExecuteSqlCommandAsync和FromSql现在已过时,您可以在代码注释中看到它:

[Obsolete("For the async execution of SQL queries using plain strings, use ExecuteSqlRawAsync instead. For the async execution of SQL queries using interpolated string syntax to create parameters, use ExecuteSqlInterpolatedAsync instead.")]
public static Task<int> ExecuteSqlCommandAsync([NotNull] this DatabaseFacade databaseFacade, RawSqlString sql, [NotNull] IEnumerable<object> parameters, CancellationToken cancellationToken = default);

[Obsolete("For returning objects from SQL queries using plain strings, use FromSqlRaw instead. For returning objects from SQL queries using interpolated string syntax to create parameters, use FromSqlInterpolated instead. Call either new method directly on the DbSet at the root of the query.", true)]
public static IQueryable<TEntity> FromSql<TEntity>([JetBrains.Annotations.NotNull] this IQueryable<TEntity> source, [JetBrains.Annotations.NotNull] [NotParameterized] FormattableString sql) where TEntity : class

带有参数的新api是:

public static Task<int> ExecuteSqlInterpolatedAsync([JetBrains.Annotations.NotNull] this DatabaseFacade databaseFacade, [JetBrains.Annotations.NotNull] FormattableString sql, CancellationToken cancellationToken = default(CancellationToken))
public static IQueryable<TEntity> FromSqlInterpolated<TEntity>([JetBrains.Annotations.NotNull] this DbSet<TEntity> source, [JetBrains.Annotations.NotNull] [NotParameterized] FormattableString sql) where TEntity : class

例如,这些新的API使用FormattableString作为参数

string parm1="A";
string parm2="B";
_dbContext.Database.ExecuteSqlInterpolatedAsync($"EXEC proc @parm1={parm1},@parm2={parm2}");

@ parm1在您的数据库过程中定义,{parm1}来自csharp字符串parm1值

FromSql详细信息:https://docs.microsoft.com/en-us/ef/core/querying/raw-sql

答案 1 :(得分:0)

因此,这是我从GitHub获得的解决方案。我要做的就是用注释中提到的@IvanStoev替换成ToList()的SingleOrDefault()。

如果有人将来需要,我只是在这里添加。

var res = await _context
           .Restaurants
           .FromSqlInterpolated($"UpdateRestaurantInformation {restaurant.RestaurantId}, {restaurant.RestaurantName}, {restaurant.Location.LocationId}").ToListAsync();

return res.SingleOrDefault();