Как выполнить хранимую процедуру для нескольких параметров с помощью FromSqlInterpolated в 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 (результат задачи)

Что я здесь ошибаюсь? Пожалуйста, кто-нибудь, помогите мне.


person Community    schedule 03.12.2019    source источник
comment
Замените .SingleAsync() на .ToListAsync().   -  person Ivan Stoev    schedule 03.12.2019


Ответы (2)


Итак, это решение, которое я получил от GitHub. Все, что мне нужно было сделать, это заменить SingleOrDefault() на ToList(), как упоминал @IvanStoev в комментарии.

Я просто добавляю это сюда, если кому-то это понадобится в будущем.

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

return res.SingleOrDefault();
person Community    schedule 03.12.2019

Вы можете узнать, как использовать команду sql в ядре ef с помощью этой статьи:

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

По мере обновления efcore. Вам не нужно создавать SqlParameter в новом API efcore.

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} взят из значения parm1 строки csharp.

Детали FromSql: https://docs.microsoft.com/en-us/ef/core/querying/raw-sql#passing-parameters

person ws_    schedule 03.12.2019
comment
Пожалуйста, добавьте некоторые пояснения к вашему ответу. - person Sampada; 03.12.2019
comment
@Sampada Я добавил некоторые пояснения. Пожалуйста, проверьте это. - person ws_; 05.12.2019