7

我在 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(任务结果)

我在这里误会了什么?请有人帮助我。

4

2 回答 2

9

所以,这是我从GitHub得到的解决方案。我所要做的就是用评论中提到的@IvanStoev 用 ToList() 替换 SingleOrDefault() 。

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

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

return res.SingleOrDefault();
于 2019-12-03T16:05:34.387 回答
3

您可以通过这篇文章了解如何在 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#passing-parameters

于 2019-12-03T07:01:13.270 回答