web-dev-qa-db-fra.com

Comment exécuter une procédure stockée pour plusieurs paramètres à l'aide de FromSqlInterpolated dans EF Core 3.0?

J'ai un procédure stockée dans Sql Server 2017 qui prend trois paramètres.

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

Lorsque j'ai essayé d'exécuter cette procédure stockée en utilisant l'extrait de code ci-dessous, Cela a fonctionné comme prévu.

   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();

Mais quand j'ai essayé d'utiliser FromSqlInterpolated comme ceci ci-dessous:

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

Il lève cette exception:

SqlException: syntaxe incorrecte près de '@ p0'. Microsoft.Data.SqlClient.SqlCommand + <> c.b__164_0 (résultat de la tâche)

Que me trompe-je ici? S'il vous plaît, quelqu'un m'aide.

2

Vous pouvez apprendre à utiliser la commande sql dans ef core avec cet artical:

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

Comme mis à jour efcore. Vous n'avez pas besoin de construire SqlParameter dans la nouvelle API efcore.

ExecuteSqlCommandAsync et FromSql est obsolète maintenant, vous pouvez le voir dans le commentaire de code:

[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

Les nouveaux apis avec params sont:

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

Ces nouveaux apis utilisent FormattableString comme param, par exemple

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

@ parm1 est défini dans votre procédure de base de données, {parm1} provient de la valeur parm1 de la chaîne csharp

Détails FromSql: https://docs.Microsoft.com/en-us/ef/core/querying/raw-sql

1
ws_

Donc, c'est la solution que j'ai obtenue de GitHub . Tout ce que j'avais à faire était de remplacer SingleOrDefault () par ToList () comme @IvanStoev mentionné dans le commentaire.

J'ajoute simplement ceci ici si quelqu'un en a besoin à l'avenir.

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

return res.SingleOrDefault();
0