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

12

我在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(Task result)

我在哪里犯错了?请有人帮帮我。


1
请将.SingleAsync()替换为.ToListAsync() - Ivan Stoev
3个回答

14

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

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

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

return res.SingleOrDefault();

6
你可以通过这篇文章学习如何在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使用可格式化字符串作为参数,例如。
string parm1="A";
string parm2="B";
_dbContext.Database.ExecuteSqlInterpolatedAsync($"EXEC proc @parm1={parm1},@parm2={parm2}");

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

FromSql详情:https://learn.microsoft.com/en-us/ef/core/querying/raw-sql#passing-parameters


请在您的答案中添加一些解释。 - Sampada
1
@Sampada 我添加了一些解释,请查看。 - ws_

1

我遇到了这个问题,我也有同样的问题,即如何从ef core执行存储过程,我尝试的解决方案如下:

下面的函数尝试根据状态作为给定输入来获取person表中的所有人,并且没有返回我想要的正确答案。

public void GetPersonsByStateInterpolated()
{
    string state = "IL";
    var persons = _context.Persons.FromSqlInterpolated($"GetPersonsByState
    {state}").ToList();
    Assert.AreEqual(2, persons.Count);
}

我为解决上述函数中的问题所做的修复如下: 我将执行存储过程的函数从“FromSQLInterpolated”更改为“FromSqlRaw” 下面的代码解释了这个变化。

public void GetPersonByStateInterpolated()
        {
            string state = "IL";
            var persons = _context.Persons.
                          FromSqlRaw($"GetPersonsByState @p0",
                          new[] {state}).ToList();
           
       
            Assert.AreEqual(2, persons.Count);
        }

希望这可以帮到您

了解更多有关 FromSqlRaw 参数的解释。

它有两个主要参数:

  1. 第一个参数是您存储过程的名称,与上面的函数中解释的一个参数连接在一起。
  2. 第二个参数是您将要发送的参数数组。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接