Query SQL non elaborata senza DbSet - Entity Framework Core


107

Con la rimozione di Entity Framework Core dbData.Database.SqlQuery<SomeModel>non riesco a trovare una soluzione per creare una query SQL non elaborata per la mia query di ricerca full-text che restituirà i dati delle tabelle e anche il ranking.

L'unico metodo che ho visto per creare una query SQL dbData.Product.FromSql("SQL SCRIPT");non elaborata in Entity Framework Core è tramite il quale non è utile poiché non ho DbSet che mapperà il rango restituito nella query.

Qualche idea???


15
Mi mancherà molto SqlQuery <T> e non voglio dover mappare classi personalizzate al mio DbContext quando ho davvero bisogno di un semplice DTO per un caso d'uso specifico. Ho creato una voce utente per richiedere l'aggiunta di questa funzione in EF Core che chiunque può votare se desidera che questa funzione venga
Matt Sanders

1
Secondo github.com/aspnet/EntityFramework/issues/1862 , questo è ora mirato per EF core 1.2 e / o 1.1.0-preview1
Dan Field

2
Basandomi su ciò che ha appena detto @Devon, ho passato troppo tempo a capire che sono metodi di estensione in Microsoft.EntityFrameworkCore.SqlServer. Dovrai aggiungerlo al tuo progetto prima di ottenere questi metodi di estensione.
Daniel

3
Sigh questa sembra una sorta di decisione di Architecture Astronaut: "le persone non dovrebbero aver bisogno di volerlo". Immagino di dover installare Dapper solo per questo caso. Fastidioso.
Dirk Boer

1
@ MattSanders - il tuo link uservoice sembra essere morto nel frattempo. Sai dove è andato?
Dirk Boer

Risposte:


127

Dipende se usi EF Core 2.1 o EF Core 3 e versioni successive .

Se usi EF Core 2.1

Se usi EF Core 2.1 Release Candidate 1 disponibile dal 7 maggio 2018, puoi sfruttare la nuova funzionalità proposta che è il tipo di query.

Cos'è il tipo di query ?

Oltre ai tipi di entità, un modello EF Core può contenere tipi di query, che possono essere usati per eseguire query di database su dati non mappati a tipi di entità.

Quando utilizzare il tipo di query?

Serve come 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 eseguire tutti gli hack o le 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 di colonna della tua query SQL. Quindi nel tuo DbContextavrai questo:

public DbQuery<SomeModel> SomeModels { get; set; }

In secondo luogo, usa il FromSqlmetodo 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 le DdContexts sono classi parziali , quindi è possibile creare uno o più file separati per organizzare le definizioni di "SQL DbQuery non elaborate" come meglio si adatta alle proprie esigenze.


Se usi EF Core 3.0 e versioni successive

Il tipo di query è ora noto come tipo di entità senza chiave . Come detto sopra, i tipi di query sono stati introdotti in EF Core 2.1. Se usi EF Core 3.0 o versione successiva, dovresti ora considerare l'uso di tipi di entità senza chiave perché i tipi di query sono ora contrassegnati come obsoleti.

Questa funzionalità è stata aggiunta in EF Core 2.1 con il nome di tipi di query. In EF Core 3.0 il concetto è stato rinominato in tipi di entità senza chiave. L'annotazione dei dati [senza chiave] è diventata disponibile in EFCore 5.0.

Abbiamo ancora gli stessi scenari dei tipi di query per quando utilizzare il tipo di entità senza chiave.

Quindi per usarlo devi prima contrassegnare la tua classe SomeModelcon [Keyless]l'annotazione dei dati o attraverso una configurazione fluente con la .HasNoKey()chiamata al metodo come di seguito:

public DbSet<SomeModel> SomeModels { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<SomeModel>().HasNoKey();
}

Dopo quella configurazione, puoi utilizzare uno dei metodi spiegati qui per eseguire la tua query SQL. Ad esempio puoi usare questo:

var result = context.SomeModels.FromSqlRaw("SQL SCRIPT").ToList();

18
Questa risposta dovrebbe essere la soluzione migliore quando si usa EF Core 2.1 e versioni successive. 👍
Will Huang

2
@CodeNotFound E se non avessi bisogno del risultato o se fosse un tipo primitivo (ad esempio bit)?
Shimmy Weitzhandler

5
Usando CodeFirst questo ha creato automaticamente una tabella con tutte quelle proprietà, l'aggiunta [NotMapped]alla SomeModelsclasse non funziona per me. Mi sono perso qualcosa?
Jean-Paul,

7
EF Core 3.0 è deprecato DbQuerya favore dell'utilizzo solo DbSetcon tipi di entità senza chiave .
NetMage

3
Solo per tua informazione, a causa di alcuni bug in EF core 3.0, una migrazione code first proverà comunque a creare una tabella anche su entità contrassegnate con HasNoKey (). Quindi devi fare anche aggiungere .ToView (null). Ad esempio, modelBuilder.Entity<MyData>().HasNoKey().ToView(null);@ Jean-Paul Penso che questo risolva il tuo problema
stann1

36

Basandomi sulle altre risposte ho scritto questo helper che svolge l'attività, incluso l'utilizzo di esempio:

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

Utilizzo:

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 sbarazzarmene non appena verrà aggiunto il supporto integrato. Secondo una dichiarazione di Arthur Vickers del team EF Core, è una priorità assoluta per il post 2.0. Il problema viene monitorato qui .


bella risposta, mi è piaciuto.
sebu

31

In EF Core non è più possibile eseguire sql raw "gratuito". È necessario definire una classe POCO e una DbSetper quella classe. Nel tuo caso dovrai definire il Rank :

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

Dato che sarà sicuramente di sola lettura, sarà utile includere la .AsNoTracking()chiamata.

EDIT - Cambiamento decisivo in EF Core 3.0:

DbQuery () è ora obsoleto, invece DbSet () dovrebbe essere utilizzato (di nuovo). Se hai un'entità senza chiave, ovvero non richiede la chiave primaria, puoi utilizzare il metodo HasNoKey () :

ModelBuilder.Entity<SomeModel>().HasNoKey()

Ulteriori informazioni possono essere trovate qui


3
Quindi immagino che dovrò anche estendere il DbContextper includere una nuova proprietà DbSet<Rank> Rank { get; set; }. Quali implicazioni avrà ora questo in riferimento a linq? Cioè, non saremo ora in grado di utilizzare un'istruzione simile DBContext.Rank.Where(i => i.key == 1)e questa istruzione non avrà alcuna implementazione in SQL e quindi fallirà?
David Harlow

Linq emesso contro questo set deve essere risolto in memoria. Se è necessario emettere clausole WHERE sql diverse, è necessario includerle come parametri o creare uno script diverso.
E-Bat

Il mio DbSet non ha un metodo "FromSql". È un'estensione che mi manca?
birwin

1
@birwin, devi importare lo spazio dei nomi Microsoft.EntityFrameworkCore
E-Bat

20

Puoi eseguire sql non elaborato in EF Core: aggiungi questa classe al tuo progetto. Ciò ti consentirà di eseguire SQL non elaborato e ottenere risultati non elaborati senza dover definire un POCO e un DBSet. Vedi https://github.com/aspnet/EntityFramework/issues/1862#issuecomment-220787464 per un esempio originale.

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

Ecco un esempio di come usarlo:

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

18

Per ora, fino a quando non ci sarà qualcosa di nuovo da EFCore, userei un comando e lo mapperei manualmente

  using (var command = this.DbContext.Database.GetDbConnection().CreateCommand())
  {
      command.CommandText = "SELECT ... WHERE ...> @p1)";
      command.CommandType = CommandType.Text;
      var parameter = new SqlParameter("@p1",...);
      command.Parameters.Add(parameter);

      this.DbContext.Database.OpenConnection();

      using (var result = command.ExecuteReader())
      {
         while (result.Read())
         {
            .... // Map to your entity
         }
      }
  }

Prova a SqlParameter per evitare Sql Injection.

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

FromSql non funziona con la query completa. Esempio, se si desidera includere una clausola WHERE, verrà ignorata.

Alcuni link:

Esecuzione di query SQL non elaborate utilizzando Entity Framework Core

Query SQL non elaborate


7

In Core 2.1 puoi fare qualcosa del genere:

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

e quindi definire la procedura SQL, come:

public async Task<List<Ranks>> GetRanks(string value1, Nullable<decimal> value2)
{
    SqlParameter value1Input = new SqlParameter("@Param1", value1?? (object)DBNull.Value);
    SqlParameter value2Input = new SqlParameter("@Param2", value2?? (object)DBNull.Value);

    List<Ranks> getRanks = await this.Query<Ranks>().FromSql("STORED_PROCEDURE @Param1, @Param2", value1Input, value2Input).ToListAsync();

    return getRanks;
}

In questo modo il modello Ranks non verrà creato nel tuo DB.

Ora nel tuo controller / azione puoi chiamare:

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

In questo modo puoi chiamare Raw SQL Procedures.


I FromSqlparametri possono essere semplicemente passati senza creare SqlParameteroggetto: FromSql($"STORED_PROCEDURE {value1}, {value2}")o FromSql("STORED_PROCEDURE {0}, {1}", value1, value2)(verranno evitati).
Majid

7

Puoi usarlo (da https://github.com/aspnet/EntityFrameworkCore/issues/1862#issuecomment-451671168 ):

public static class SqlQueryExtensions
{
    public static IList<T> SqlQuery<T>(this DbContext db, string sql, params object[] parameters) where T : class
    {
        using (var db2 = new ContextForQueryType<T>(db.Database.GetDbConnection()))
        {
            return db2.Query<T>().FromSql(sql, parameters).ToList();
        }
    }

    private class ContextForQueryType<T> : DbContext where T : class
    {
        private readonly DbConnection connection;

        public ContextForQueryType(DbConnection connection)
        {
            this.connection = connection;
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            // switch on the connection type name to enable support multiple providers
            // var name = con.GetType().Name;
            optionsBuilder.UseSqlServer(connection, options => options.EnableRetryOnFailure());

            base.OnConfiguring(optionsBuilder);
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Query<T>();
            base.OnModelCreating(modelBuilder);
        }
    }
}

E l'utilizzo:

    using (var db = new Db())
    {
        var results = db.SqlQuery<ArbitraryType>("select 1 id, 'joe' name");
        //or with an anonymous type like this
        var results2 = db.SqlQuery(() => new { id =1, name=""},"select 1 id, 'joe' name");
    }

6

Aggiungi il pacchetto Nuget - Microsoft.EntityFrameworkCore.Relational

using Microsoft.EntityFrameworkCore;
...
await YourContext.Database.ExecuteSqlCommandAsync("... @p0, @p1", param1, param2 ..)

Ciò restituirà i numeri di riga come un int

Vedi: https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.relationaldatabasefacadeextensions.executesqlcommand?view=efcore-3.0


3
Si ricorda che questa restituirà solo il numero di righe interessate dal comando: stackoverflow.com/a/49861799/299756
kalyfe

Esattamente quello di cui ho bisogno. Sto usando Microsoft.EntityFrameworkCore 3.1.1 e non ho modo di eseguire query RAW e SP. Grazie molte per questo!
jaysonragasa

5

prova questo: (crea un metodo di estensione)

public static List<T> ExecuteQuery<T>(this dbContext db, string query) where T : class, new()
        {
            using (var command = db.Database.GetDbConnection().CreateCommand())
            {
                command.CommandText = query;
                command.CommandType = CommandType.Text;

                db.Database.OpenConnection();

                using (var reader = command.ExecuteReader())
                {
                    var lst = new List<T>();
                    var lstColumns = new T().GetType().GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).ToList();
                    while (reader.Read())
                    {
                        var newObject = new T();
                        for (var i = 0; i < reader.FieldCount; i++)
                        {
                            var name = reader.GetName(i);
                            PropertyInfo prop = lstColumns.FirstOrDefault(a => a.Name.ToLower().Equals(name.ToLower()));
                            if (prop == null)
                            {
                                continue;
                            }
                            var val = reader.IsDBNull(i) ? null : reader[i];
                            prop.SetValue(newObject, val, null);
                        }
                        lst.Add(newObject);
                    }

                    return lst;
                }
            }
        }

Utilizzo:

var db = new dbContext();
string query = @"select ID , Name from People where ... ";
var lst = db.ExecuteQuery<PeopleView>(query);

il mio modello: (non in DbSet):

public class PeopleView
{
    public int ID { get; set; }
    public string Name { get; set; }
}

testato in .netCore 2.2 and 3.0.

Nota: questa soluzione ha prestazioni lente


Prova a cercare PropertyInfo per nome solo una volta per un solo primo record e crea un array di PropertyInfo [] in base agli indici di colonna da utilizzare nei record successivi.
Petr Voborník

@AminRostami Nice Work
sebu

2

Non prendendo di mira direttamente lo scenario dell'OP, ma poiché ho lottato con questo, mi piacerebbe abbandonare questi ex. metodi che semplificano l'esecuzione di SQL raw con DbContext:

public static class DbContextCommandExtensions
{
  public static async Task<int> ExecuteNonQueryAsync(this DbContext context, string rawSql,
    params object[] parameters)
  {
    var conn = context.Database.GetDbConnection();
    using (var command = conn.CreateCommand())
    {
      command.CommandText = rawSql;
      if (parameters != null)
        foreach (var p in parameters)
          command.Parameters.Add(p);
      await conn.OpenAsync();
      return await command.ExecuteNonQueryAsync();
    }
  }

  public static async Task<T> ExecuteScalarAsync<T>(this DbContext context, string rawSql,
    params object[] parameters)
  {
    var conn = context.Database.GetDbConnection();
    using (var command = conn.CreateCommand())
    {
      command.CommandText = rawSql;
      if (parameters != null)
        foreach (var p in parameters)
          command.Parameters.Add(p);
      await conn.OpenAsync();
      return (T)await command.ExecuteScalarAsync();
    }
  }
}

1

Ho usato Dapper per aggirare questo vincolo di Entity framework Core.

IDbConnection.Query

sta lavorando con query sql o stored procedure con più parametri. A proposito è un po 'più veloce (vedi test benchmark )

Dapper è facile da imparare. Sono stati necessari 15 minuti per scrivere ed eseguire la stored procedure con i parametri. Ad ogni modo puoi usare sia EF che Dapper. Di seguito è riportato un esempio:

 public class PodborsByParametersService
{
    string _connectionString = null;


    public PodborsByParametersService(string connStr)
    {
        this._connectionString = connStr;

    }

    public IList<TyreSearchResult> GetTyres(TyresPodborView pb,bool isPartner,string partnerId ,int pointId)
    {

        string sqltext  "spGetTyresPartnerToClient";

        var p = new DynamicParameters();
        p.Add("@PartnerID", partnerId);
        p.Add("@PartnerPointID", pointId);

        using (IDbConnection db = new SqlConnection(_connectionString))
        {
            return db.Query<TyreSearchResult>(sqltext, p,null,true,null,CommandType.StoredProcedure).ToList();
        }


        }
}

0

Puoi anche usare QueryFirst . Come Dapper, questo è totalmente al di fuori di EF. A differenza di Dapper (o EF), non è necessario mantenere il POCO, si modifica il SQL SQL in un ambiente reale e viene continuamente riconvalidato rispetto al DB. Disclaimer: sono l'autore di QueryFirst.


0

Il mio caso ha utilizzato una procedura memorizzata invece di SQL grezzo

Creato un corso

Public class School
{
    [Key]
    public Guid SchoolId { get; set; }
    public string Name { get; set; }
    public string Branch { get; set; }
    public int NumberOfStudents  { get; set; }
}

Aggiunto di seguito sulla mia DbContextclasse

public DbSet<School> SP_Schools { get; set; }

Per eseguire la procedura memorizzata:

var MySchools = _db.SP_Schools.FromSqlRaw("GetSchools @schoolId, @page, @size ",
              new SqlParameter("schoolId", schoolId),
              new SqlParameter("page", page),
              new SqlParameter("size", size)))
.IgnoreQueryFilters();


0

Questa soluzione si basa molto sulla soluzione di @pius. Volevo aggiungere l'opzione per supportare i parametri di query per aiutare a mitigare l'iniezione SQL e volevo anche renderlo un'estensione di DbContext DatabaseFacade per Entity Framework Core per renderlo un po 'più integrato.

Per prima cosa crea una nuova classe con l'estensione:

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Threading.Tasks;

namespace EF.Extend
{

    public static class ExecuteSqlExt
    {
        /// <summary>
        /// Execute raw SQL query with query parameters
        /// </summary>
        /// <typeparam name="T">the return type</typeparam>
        /// <param name="db">the database context database, usually _context.Database</param>
        /// <param name="query">the query string</param>
        /// <param name="map">the map to map the result to the object of type T</param>
        /// <param name="queryParameters">the collection of query parameters, if any</param>
        /// <returns></returns>
        public static List<T> ExecuteSqlRawExt<T, P>(this DatabaseFacade db, string query, Func<DbDataReader, T> map, IEnumerable<P> queryParameters = null)
        {
            using (var command = db.GetDbConnection().CreateCommand())
            {
                if((queryParameters?.Any() ?? false))
                    command.Parameters.AddRange(queryParameters.ToArray());

                command.CommandText = query;
                command.CommandType = CommandType.Text;

                db.OpenConnection();

                using (var result = command.ExecuteReader())
                {
                    var entities = new List<T>();

                    while (result.Read())
                    {
                        entities.Add(map(result));
                    }

                    return entities;
                }
            }
                
        }
    }

}

Nota in quanto sopra che "T" è il tipo per la restituzione e "P" è il tipo dei parametri della tua query che varieranno in base se stai usando MySql, Sql e così via.

Successivamente mostreremo un esempio. Sto usando la funzionalità MySql EF Core, quindi vedremo come possiamo usare l'estensione generica sopra con questa implementazione MySql più specifica:

//add your using statement for the extension at the top of your Controller
//with all your other using statements
using EF.Extend;

//then your your Controller looks something like this
namespace Car.Api.Controllers
{

    //Define a quick Car class for the custom return type
    //you would want to put this in it's own class file probably
    public class Car
    {
        public string Make { get; set; }
        public string Model { get; set; }
        public string DisplayTitle { get; set; }
    }

    [ApiController]
    public class CarController : ControllerBase
    {
        private readonly ILogger<CarController> _logger;
        //this would be your Entity Framework Core context
        private readonly CarContext _context;

        public CarController(ILogger<CarController> logger, CarContext context)
        {
            _logger = logger;
            _context = context;
        }

        //... more stuff here ...

       /// <summary>
       /// Get car example
       /// </summary>
       [HttpGet]
       public IEnumerable<Car> Get()
       {
           //instantiate three query parameters to pass with the query
           //note the MySqlParameter type is because I'm using MySql
           MySqlParameter p1 = new MySqlParameter
           {
               ParameterName = "id1",
               Value = "25"
           };

           MySqlParameter p2 = new MySqlParameter
           {
               ParameterName = "id2",
               Value = "26"
           };

           MySqlParameter p3 = new MySqlParameter
           {
               ParameterName = "id3",
               Value = "27"
           };

           //add the 3 query parameters to an IEnumerable compatible list object
           List<MySqlParameter> queryParameters = new List<MySqlParameter>() { p1, p2, p3 };

           //note the extension is now easily accessed off the _context.Database object
           //also note for ExecuteSqlRawExt<Car, MySqlParameter>
           //Car is my return type "T"
           //MySqlParameter is the specific DbParameter type MySqlParameter type "P"
           List<Car> result = _context.Database.ExecuteSqlRawExt<Car, MySqlParameter>(
        "SELECT Car.Make, Car.Model, CONCAT_WS('', Car.Make, ' ', Car.Model) As DisplayTitle FROM Car WHERE Car.Id IN(@id1, @id2, @id3)",
        x => new Car { Make = (string)x[0], Model = (string)x[1], DisplayTitle = (string)x[2] }, 
        queryParameters);

           return result;
       }
    }
}

La query restituisce righe come:
"Ford", "Explorer", "Ford Explorer"
"Tesla", "Model X", "Tesla Model X"

Il titolo visualizzato non è definito come una colonna del database, quindi per impostazione predefinita non farebbe parte del modello EF Car. Mi piace questo approccio come una delle tante possibili soluzioni. Le altre risposte in questa pagina fanno riferimento ad altri modi per risolvere questo problema con il decoratore [NotMapped], che a seconda del caso d'uso potrebbe essere l'approccio più appropriato.

Nota che il codice in questo esempio è ovviamente più prolisso di quanto dovrebbe essere, ma ho pensato che rendesse l'esempio più chiaro.


-6

Con Entity Framework 6 puoi eseguire qualcosa come di seguito

Crea classe modale come

Public class User
{
        public int Id { get; set; }
        public string fname { get; set; }
        public string lname { get; set; }
        public string username { get; set; }
}

Esegui il comando Raw DQL SQl come di seguito:

var userList = datacontext.Database.SqlQuery<User>(@"SELECT u.Id ,fname , lname ,username FROM dbo.Users").ToList<User>();
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.