SQL Server 2017にストアドプロシージャがあり、3つのパラメーターを取ります。
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
以下のコードスニペットを使用してこのストアドプロシージャを実行しようとすると、予想どおりIt worksになりました。
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(タスク結果)
ここで何を間違えていますか?誰か助けてください。
次の記事では、efコアでsqlコマンドを使用する方法を学ぶことができます。
https://www.learnentityframeworkcore.com/raw-sql#stored-procedureshttps://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
だから、これは私が GitHub から得たソリューションです。 @IvanStoevがコメントで述べたように、私がしなければならなかったのは、SingleOrDefault()をToList()に置き換えることだけでした。
将来誰かがこれを必要とする場合は、ここに追加します。
var res = await _context
.Restaurants
.FromSqlInterpolated($"UpdateRestaurantInformation {restaurant.RestaurantId}, {restaurant.RestaurantName}, {restaurant.Location.LocationId}").ToListAsync();
return res.SingleOrDefault();