Raw SQL Query ohne DbSet – Entity Framework Core

dbData.Database.SqlQuery Entity Framework Core entfernt wird dbData.Database.SqlQuery Ich kann keine Lösung finden, um eine dbData.Database.SqlQuery SQL-Abfrage für meine Volltextsuche zu erstellen, die die Tabellendaten und auch den Rang dbData.Database.SqlQuery .

Die einzige Methode, die ich gesehen habe, um eine dbData.Product.FromSql("SQL SCRIPT"); SQL-Abfrage in Entity Framework Core zu dbData.Product.FromSql("SQL SCRIPT"); ist über dbData.Product.FromSql("SQL SCRIPT"); Das ist nicht nützlich, da ich kein DbSet habe, das den Rang abbilden würde, den ich in der Abfrage zurückgebe.

Irgendwelche Ideen???

In EF Core können Sie nicht mehr “freie” rohe SQL ausführen. Sie müssen eine POCO-class und ein DbSet für diese class definieren. In Ihrem Fall müssen Sie den Rang definieren:

 var ranks = DbContext.Ranks .FromSql("SQL_SCRIPT OR STORED_PROCEDURE @p0,@p1,...etc", parameters) .AsNoTracking().ToList(); 

Da es sicher nur gelesen werden wird, wird es nützlich sein, den .AsNoTracking() Aufruf .AsNoTracking() .

Sie können root sql in EF Core ausführen – Fügen Sie diese class zu Ihrem Projekt hinzu. Dadurch können Sie Raw SQL ausführen und die rohen Ergebnisse erhalten, ohne ein POCO und ein DBSet definieren zu müssen. Das Originalbeispiel finden Sie unter 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(); using (concurrencyDetector.EnterCriticalSection()) { var rawSqlCommand = databaseFacade .GetService() .Build(sql, parameters); return rawSqlCommand .RelationalCommand .ExecuteReader( databaseFacade.GetService(), parameterValues: rawSqlCommand.ParameterValues); } } public static async Task ExecuteSqlQueryAsync(this DatabaseFacade databaseFacade, string sql, CancellationToken cancellationToken = default(CancellationToken), params object[] parameters) { var concurrencyDetector = databaseFacade.GetService(); using (concurrencyDetector.EnterCriticalSection()) { var rawSqlCommand = databaseFacade .GetService() .Build(sql, parameters); return await rawSqlCommand .RelationalCommand .ExecuteReaderAsync( databaseFacade.GetService(), parameterValues: rawSqlCommand.ParameterValues, cancellationToken: cancellationToken); } } } } 

Hier ist ein Beispiel, wie man es benutzt:

 // 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]); } } 

Aufbauend auf den anderen Antworten habe ich diesen Helfer geschrieben, der die Aufgabe erfüllt, einschließlich Beispielverwendung:

 public static class Helper { public static List RawSqlQuery(string query, Func 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(); while (result.Read()) { entities.Add(map(result)); } return entities; } } } } 

Verwendung:

 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}")); 

Ich plane, es loszuwerden, sobald die eingebaute Unterstützung hinzugefügt wird. Laut einer Aussage von Arthur Vickers vom EF Core Team hat dies eine hohe Priorität für Post 2.0. Das Problem wird hier verfolgt.

Wenn Sie EF Core 2.1 Release Candidate 1 seit dem 7. Mai 2018 verwenden, können Sie die vorgeschlagene neue function, die der Abfragetyp ist, nutzen.

Was ist der Abfragetyp ?

Zusätzlich zu Entitätstypen kann ein EF Core-Modell Abfragetypen enthalten, die verwendet werden können, um databaseabfragen für Daten auszuführen, die keinen Entitätstypen zugeordnet sind.

Wann muss der Abfragetyp verwendet werden?

Als Rückgabetyp für Ad-hoc-FromSql () -Abfragen dienen.

Zuordnung zu databaseansichten

Zuordnen zu Tabellen, für die kein Primärschlüssel definiert ist.

Zuordnung zu im Modell definierten Abfragen

Sie müssen also nicht mehr alle Hacks oder Workarounds als Antworten auf Ihre Frage ausführen. Befolgen Sie einfach diese Schritte:

Zuerst haben Sie eine neue Eigenschaft vom Typ DbQuery wobei T der Typ der class ist, die die Spaltenwerte Ihrer SQL-Abfrage enthält. Also in deinem DbContext hast du folgendes:

 public DbQuery SomeModels { get; set; } 

Zweitens verwenden FromSql Methode wie Sie mit DbSet tun:

 var result = context.SomeModels.FromSql("SQL_SCRIPT").ToList(); 

Für den Moment, bis es etwas neues von EFCore gibt, würde ich einen Befehl verwenden und ihn manuell zuordnen

  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 } } } 

Versuchen Sie SqlParameter, Sql-Injektion zu vermeiden.

  dbData.Product.FromSql("SQL SCRIPT"); 

FromSql funktioniert nicht mit vollständiger Abfrage. Beispiel wenn Sie eine WHERE-Klausel einfügen wollen, wird diese ignoriert.

Einige Links:

Ausführen von Raw SQL-Abfragen mit Entity Framework Core

Raw SQL-Abfragen

In Core 2.1 können Sie so etwas tun:

 protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Query(); } 

und dann definieren Sie SQL-Prozedur, wie:

 public async Task> GetRanks(string value1, Nullable value2) { SqlParameter value1Input = new SqlParameter("@Param1", value1?? (object)DBNull.Value); SqlParameter value2Input = new SqlParameter("@Param2", value2?? (object)DBNull.Value); List getRanks = await this.Query().FromSql("STORED_PROCEDURE @Param1, @Param2", value1Input, value2Input).ToListAsync(); return getRanks; } 

Auf diese Weise wird das Ränge-Modell nicht in Ihrer database erstellt.

Jetzt in Ihrem Controller / Aktion können Sie anrufen:

 List gettingRanks = _DbContext.GetRanks(value1,value2).Result.ToListAsync(); 

Auf diese Weise können Sie Raw SQL-Prozeduren aufrufen.