隨着實體框架核心刪除dbData.Database.SqlQuery<SomeModel>
我找不到解決方案爲我的全文搜索查詢構建原始SQL查詢,該查詢將返回表數據和等級。沒有DbSet的原始SQL查詢 - 實體框架核心
我在Entity Framework Core中構建原始SQL查詢的唯一方法是通過dbData.Product.FromSql("SQL SCRIPT");
,這是沒有用的,因爲我沒有DbSet將映射查詢中返回的排名。
任何想法???
隨着實體框架核心刪除dbData.Database.SqlQuery<SomeModel>
我找不到解決方案爲我的全文搜索查詢構建原始SQL查詢,該查詢將返回表數據和等級。沒有DbSet的原始SQL查詢 - 實體框架核心
我在Entity Framework Core中構建原始SQL查詢的唯一方法是通過dbData.Product.FromSql("SQL SCRIPT");
,這是沒有用的,因爲我沒有DbSet將映射查詢中返回的排名。
任何想法???
在EF Core中,您不再可以執行「免費」原始sql。您需要爲該類定義POCO類和DbSet
。 在你的情況,你需要定義排名:
var ranks = DbContext.Ranks
.FromSql("SQL_SCRIPT OR STORED_PROCEDURE @p0,@p1,...etc", parameters)
.AsNoTracking().ToList();
由於這將是肯定只讀這將是有益的包括.AsNoTracking()
電話。
所以我想我也必須擴展'DbContext'以包含一個新屬性'DbSet
Linq排出的這組數據必須在內存中解決。如果您需要發出不同的WHERE sql子句,則必須將它們包含爲參數或構建不同的腳本。 –
我的DbSet沒有「FromSql」方法。這是我失蹤的擴展嗎? – birwin
您可以在EF Core中執行raw sql - 將此類添加到您的項目中。 這將允許您執行原始SQL並獲取原始結果,而無需定義POCO和DBSet。 原始示例請參見https://github.com/aspnet/EntityFramework/issues/1862#issuecomment-220787464。
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Storage;
using System.Threading;
using System.Threading.Tasks;
namespace Microsoft.EntityFrameworkCore
{
public static class RDFacadeExtensions
{
public static RelationalDataReader ExecuteSqlQuery(this DatabaseFacade databaseFacade, string sql, params object[] parameters)
{
var concurrencyDetector = databaseFacade.GetService<IConcurrencyDetector>();
using (concurrencyDetector.EnterCriticalSection())
{
var rawSqlCommand = databaseFacade
.GetService<IRawSqlCommandBuilder>()
.Build(sql, parameters);
return rawSqlCommand
.RelationalCommand
.ExecuteReader(
databaseFacade.GetService<IRelationalConnection>(),
parameterValues: rawSqlCommand.ParameterValues);
}
}
public static async Task<RelationalDataReader> ExecuteSqlQueryAsync(this DatabaseFacade databaseFacade,
string sql,
CancellationToken cancellationToken = default(CancellationToken),
params object[] parameters)
{
var concurrencyDetector = databaseFacade.GetService<IConcurrencyDetector>();
using (concurrencyDetector.EnterCriticalSection())
{
var rawSqlCommand = databaseFacade
.GetService<IRawSqlCommandBuilder>()
.Build(sql, parameters);
return await rawSqlCommand
.RelationalCommand
.ExecuteReaderAsync(
databaseFacade.GetService<IRelationalConnection>(),
parameterValues: rawSqlCommand.ParameterValues,
cancellationToken: cancellationToken);
}
}
}
}
這裏有一個如何使用它的一個例子:
// Execute a query.
using(var dr = await db.Database.ExecuteSqlQueryAsync("SELECT ID, Credits, LoginDate FROM SamplePlayer WHERE " +
"Name IN ('Electro', 'Nitro')"))
{
// Output rows.
var reader = dr.DbDataReader;
while (reader.Read())
{
Console.Write("{0}\t{1}\t{2} \n", reader[0], reader[1], reader[2]);
}
}
現在,直到有新的東西從EFCore我會用一個命令 和手動映射它
using (var command = this.DbContext.Database.GetDbConnection().CreateCommand())
{
command.CommandText = "SELECT ... WHERE ...> @p1)";
command.CommandType = CommandType.Text;
var parameter = new SqlParameter("@p1",...);
this.DbContext.Database.OpenConnection();
using (var result = command.ExecuteReader())
{
while (result.Read())
{
.... // Map to your entity
}
}
}
嘗試使用SqlParameter來避免Sql注入。
dbData.Product.FromSql("SQL SCRIPT");
FromSql不適用於完整查詢。例如,如果你想包含一個WHERE子句,它將被忽略。
幾個環節:
建立在我寫這個幫手完成任務的其他的答案,包括用法示例:
public static class Helper
{
public static List<T> RawSqlQuery<T>(string query, Func<DbDataReader, T> map)
{
using (var context = new WannaSportContext())
{
using (var command = context.Database.GetDbConnection().CreateCommand())
{
command.CommandText = query;
command.CommandType = CommandType.Text;
context.Database.OpenConnection();
using (var result = command.ExecuteReader())
{
var entities = new List<T>();
while (result.Read())
{
entities.Add(map(result));
}
return entities;
}
}
}
}
用法:
public class TopUser
{
public string Name { get; set; }
public int Count { get; set; }
}
var result = Helper.RawSqlQuery(
"SELECT TOP 10 Name, COUNT(*) FROM Users U"
+ " INNER JOIN Signups S ON U.UserId = S.UserId"
+ " GROUP BY U.Name ORDER BY COUNT(*) DESC",
x => new TopUser { Name = (string)x[0], Count = (int)x[1] });
result.ForEach(x => Console.WriteLine($"{x.Name,-25}{x.Count}"));
我計劃一旦添加內置支持就立即擺脫它。根據EF核心團隊的Arthur Vickers的statement,這是後2.0的高優先級。該問題正在跟蹤here。
我會非常想念SqlQuery,並且不想將自定義類映射到我的DbContext,當我真的只需要一個簡單的DTO用於特定用例時。我創建了一個用戶語音來請求將此功能重新添加到EF Core,任何人都可以投票,如果他們希望返回此功能:https://data.uservoice。com/forums/72025-entity-framework-feature-suggestions/suggestions/13183638-add-dbcontext-database-sqlquery-to-entity-framewor –
根據https://github.com/aspnet/EntityFramework/issues/1862,這現在的目標是EF核心1.2和/或1.1.0-preview1 –