在上一篇 在 Entity Framework Core 中使用 SQL 語法查詢 中我們透過 FromSqlInterpolated 和 FromSqlRaw 關鍵字在 Entity Framework Core 中執行 SQL 查詢,並把結果直接對應到 DbSet 當中。
但是假設我們要取得資料,就要先依照回傳值建立自訂類別,假設依照回傳值自訂 ResultModel 類別,就需要先在 ApplicationDbContext 類別(這裡指的是繼承 DbContext 的類別) 中使用類似下面的語法宣告
然後才能使用 FromSqlInterpolated 和 FromSqlRaw 來取得資料
註: 本文中使用 EF Core 6.0,若使用 EF Core 7.0 或以上則會找不到 FromSqlInterpolated 關鍵字,需要使用 FromSql 取代。
如果少了 DbSet 宣告的那行,就會拋出類似下列錯誤:
如果每個查詢都要先建立回傳資料結果物件,非常麻煩,有時候我們只是想要接收個 Json 資料,然後還要再加個 DbSet,好麻煩,有沒有其他方式?
在 Entity Framework Core 中也有支援 DbConnection ,可以使用「傳統」的查詢方式:
但是假設我們要取得資料,就要先依照回傳值建立自訂類別,假設依照回傳值自訂 ResultModel 類別,就需要先在 ApplicationDbContext 類別(這裡指的是繼承 DbContext 的類別) 中使用類似下面的語法宣告
public virtual DbSet<ResultModel> Results { get; set; } = null!;
然後才能使用 FromSqlInterpolated 和 FromSqlRaw 來取得資料
// private readonly ApplicationDbContext _context;
ResultModel? result = _context.Set<ResultModel>().FromSqlInterpolated(
$"select * from result_table"
)
.FirstOrDefault();
註: 本文中使用 EF Core 6.0,若使用 EF Core 7.0 或以上則會找不到 FromSqlInterpolated 關鍵字,需要使用 FromSql 取代。
如果少了 DbSet 宣告的那行,就會拋出類似下列錯誤:
[22:44:30 ERR] An unhandled exception has occurred while executing the request.
System.InvalidOperationException: Cannot create a DbSet for 'ResultModel' because this type is not included in the model for the context.
at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.get_EntityType()
at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.CheckState()
at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.get_EntityQueryable()
at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.System.Linq.IQueryable.get_Provider()
at Microsoft.EntityFrameworkCore.RelationalQueryableExtensions.FromSqlInterpolated[TEntity](DbSet`1 source, FormattableString sql)
at ruyut.Controllers.RuyutController.Result(String categoryCode, String categoryCode2, String resolutionDate) in C:\Users\ruyut\Documents\RiderProjects\text\tcc_mis\ruyut\Controllers\RuyutController.cs:line
239
at lambda_method235(Closure , Object , Object[] )
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.Policy.AuthorizationMiddlewareResultHandler.HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
如果每個查詢都要先建立回傳資料結果物件,非常麻煩,有時候我們只是想要接收個 Json 資料,然後還要再加個 DbSet,好麻煩,有沒有其他方式?
在 Entity Framework Core 中也有支援 DbConnection ,可以使用「傳統」的查詢方式:
// private readonly ApplicationDbContext _context;
using var command = _context.Database.GetDbConnection().CreateCommand();
if (command.Connection == null) throw new Exception("Connection to database failed");
if (command.Connection?.State != ConnectionState.Open)
command.Connection?.Open();
command.CommandText = sql;
if (parameters != null)
foreach (var parameter in parameters)
{
command.Parameters.Add(new SqlParameter(parameter.Key, parameter.Value));
}
var reader = command.ExecuteReader();
while (reader.Read())
{
var str1 = reader.GetString(0);
}
if (command.Connection?.State != ConnectionState.Closed)
command.Connection?.Close();
留言
張貼留言
如果有任何問題、建議、想說的話或文章題目推薦,都歡迎留言或來信: a@ruyut.com