Ho questo codice in .Net Framework. Non c'è niente di sbagliato in questo.
// no problem in .net core
public bool ExecuteQuery(string query, params object[] parameters)
{
return _context.Database.ExecuteSqlCommand(query, parameters) > 0;
}
non trovato ( SqlQuery
) in Entity Framework Core
public List<T> SqlQuery(string query, params object[] parameters)
{
var result = _context.Database.SqlQuery<T>(query, parameters).ToList();
return result;
}
public object ExecuteNonQuery(string query, params object[] parameters)
{
var result = _context.Database.SqlQuery<string>(query, parameters);
return result;
}
Come posso scrivere lo stesso codice in .net core 2.1?
Se si utilizza EF Core 2.1 Release Candidate 1 disponibile dal 7 maggio 2018, è possibile usufruire della nuova funzione proposta che è il tipo di query.
Qual è il tipo di query ?
Oltre ai tipi di entità, un modello EF Core può contenere tipi di query, che possono essere utilizzati per eseguire query di database su dati che non sono mappati ai tipi di entità.
Quando usare il tipo di query?
Fornisce il tipo di ritorno per le query FromSql () ad hoc.
Mappatura alle viste del database.
Mappatura a tabelle che non hanno una chiave primaria definita.
Mappatura alle query definite nel modello.
Quindi non è più necessario fare tutti gli hack o soluzioni alternative proposte come risposte alla tua domanda. Segui questi passaggi:
Per prima cosa hai definito una nuova proprietà di tipo DbQuery<T>
dove T
è il tipo della classe che trasporterà i valori della colonna della tua query SQL. Quindi nel tuo DbContext
avrai questo:
public DbQuery<SomeModel> SomeModels { get; set; }
In secondo luogo usa il metodo FromSql
come fai con DbSet<T>
:
var result = context.SomeModels.FromSql("SQL_SCRIPT").ToList();
var result = await context.SomeModels.FromSql("SQL_SCRIPT").ToListAsync();
Si noti inoltre che DBContexts sono classi parziali , quindi è possibile creare uno o più file separati per organizzare le definizioni di 'DbQuery SQL raw come meglio si adatta alle proprie esigenze.
Basandomi sulle altre risposte, ho scritto questo aiutante che compie il compito, incluso un esempio di utilizzo:
public static class Helper
{
public static List<T> RawSqlQuery<T>(string query, Func<DbDataReader, T> map)
{
using (var context = new DbContext())
{
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;
}
}
}
}
Uso:
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}"));
Ho intenzione di liberarmene non appena viene aggiunto il supporto integrato. Secondo una dichiarazione di Arthur Vickers del team EF Core è una priorità assoluta per il post 2.0. Il problema è stato rintracciato qui .