Consulta SQL sin procesar sin DbSet - Entity Framework Core

107

Con la eliminación de Entity Framework Core, dbData.Database.SqlQuery<SomeModel>no puedo encontrar una solución para crear una consulta SQL sin procesar para mi consulta de búsqueda de texto completo que devolverá los datos de las tablas y también el rango.

El único método que he visto para crear una consulta SQL sin procesar en Entity Framework Core es a través de la dbData.Product.FromSql("SQL SCRIPT");cual no es útil ya que no tengo un DbSet que asigne el rango que devuelvo en la consulta.

¿¿¿Algunas ideas???

David Harlow
fuente
15
Extrañaré mucho SqlQuery <T> y no quiero tener que asignar clases personalizadas a mi DbContext cuando realmente solo necesito un DTO simple para un caso de uso específico. He creado una voz de usuario para solicitar que se vuelva a agregar esta función a EF Core para que cualquiera pueda votar si desea recuperar esta función: data.uservoice.com/forums/…
Matt Sanders
1
Según github.com/aspnet/EntityFramework/issues/1862 , esto ahora está dirigido a EF core 1.2 y / o 1.1.0-preview1
Dan Field
2
Sobre la base de lo que acaba de decir @Devon, pasé demasiado tiempo descubriendo que son métodos de extensión en Microsoft.EntityFrameworkCore.SqlServer. Deberá agregar eso a su proyecto antes de obtener estos métodos de extensión.
Daniel
3
Suspiro, esto parece una especie de decisión de Astronauta de Arquitectura: "la gente no debería necesitar querer esto". Supongo que tengo que instalar Dapper solo para este caso. Molesto.
Dirk Boer
1
@MattSanders: su enlace de voz de usuario parece estar muerto mientras tanto. ¿Sabes adónde fue?
Dirk Boer

Respuestas:

125

Depende de si está utilizando EF Core 2.1 o EF Core 3 y versiones superiores .

Si está usando EF Core 2.1

Si usa EF Core 2.1 Release Candidate 1 disponible desde el 7 de mayo de 2018, puede aprovechar la nueva característica propuesta, que es el tipo de consulta.

¿Qué es el tipo de consulta ?

Además de los tipos de entidad, un modelo EF Core puede contener tipos de consulta, que se pueden usar para realizar consultas de base de datos en datos que no están asignados a tipos de entidad.

¿Cuándo usar el tipo de consulta?

Sirve como tipo de retorno para consultas ad hoc de FromSql ().

Asignación a vistas de base de datos.

Asignación a tablas que no tienen una clave principal definida.

Mapeo de consultas definidas en el modelo.

Por lo tanto, ya no necesita hacer todos los trucos o soluciones alternativas propuestos como respuestas a su pregunta. Solo sigue estos pasos:

Primero definió una nueva propiedad de tipo DbQuery<T>donde Tes el tipo de la clase que llevará los valores de columna de su consulta SQL. Entonces en tu DbContexttendrás esto:

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

En segundo lugar, use el FromSqlmétodo como lo hace con DbSet<T>:

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

También tenga en cuenta que las DdContexts son clases parciales , por lo que puede crear uno o más archivos separados para organizar sus definiciones de 'SQL DbQuery sin procesar' como mejor le convenga.


Si usa EF Core 3.0 y versiones superiores

El tipo de consulta ahora se conoce como tipo de entidad sin clave . Como se dijo anteriormente, los tipos de consulta se introdujeron en EF Core 2.1. Si está utilizando EF Core 3.0 o una versión superior, ahora debería considerar el uso de tipos de entidad sin clave porque los tipos de consulta ahora están marcados como obsoletos.

Esta característica se agregó en EF Core 2.1 con el nombre de tipos de consulta. En EF Core 3.0, se cambió el nombre del concepto a tipos de entidad sin clave. La anotación de datos [Keyless] se hizo disponible en EFCore 5.0.

Todavía tenemos los mismos escenarios que para los tipos de consulta sobre cuándo usar el tipo de entidad sin clave.

Entonces, para usarlo, primero debe marcar su clase SomeModelcon [Keyless]anotación de datos o mediante una configuración fluida con la .HasNoKey()llamada al método como se muestra a continuación:

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

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

Después de esa configuración, puede usar uno de los métodos que se explican aquí para ejecutar su consulta SQL. Por ejemplo, puede usar este:

var result = context.SomeModels.FromSqlRaw("SQL SCRIPT").ToList();
CodeNotFound
fuente
18
Esta respuesta debería ser la mejor solución cuando se usa EF Core 2.1 y superior. 👍
Will Huang
2
@CodeNotFound ¿Qué pasa si no necesito el resultado o si es un tipo primitivo (por ejemplo bit)?
Shimmy Weitzhandler
5
Al usar CodeFirst, esto creó automáticamente una tabla con todas esas propiedades, agregar [NotMapped]a la SomeModelsclase no funciona para mí. ¿Yo me perdí algo?
Jean-Paul
7
EF Core 3.0 se desaprueba DbQuerya favor de usar solo DbSetcon tipos de entidad sin clave .
NetMage
3
Solo para su información, debido a algún error en EF core 3.0, una migración de código primero intentará crear una tabla incluso en entidades marcadas con HasNoKey (). Por lo tanto, también debe agregar .ToView (null). Por ejemplo, modelBuilder.Entity<MyData>().HasNoKey().ToView(null);@ Jean-Paul, creo que esto resuelve su problema
stann1
36

Sobre la base de las otras respuestas, he escrito este ayudante que realiza la tarea, incluido el uso de ejemplo:

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

Planeo deshacerme de él tan pronto como se agregue el soporte integrado. Según una declaración de Arthur Vickers del equipo EF Core, es una alta prioridad para la publicación 2.0. El problema se está rastreando aquí .

pio
fuente
buena respuesta, me gustó.
sebu
31

En EF Core ya no puede ejecutar sql sin formato "gratis". Debe definir una clase POCO y una DbSetpara esa clase. En su caso, deberá definir el Rango :

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

Como seguramente será de solo lectura, será útil incluir la .AsNoTracking()llamada.

EDITAR: cambio radical en EF Core 3.0:

DbQuery () ahora está obsoleto, en su lugar, DbSet () debería usarse (nuevamente). Si tiene una entidad sin clave, es decir, no requiere una clave principal, puede usar el método HasNoKey () :

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

Puede encontrar más información aquí

E-Bat
fuente
3
Así que supongo que también tendré que ampliar el DbContextpara incluir una nueva propiedad DbSet<Rank> Rank { get; set; }. ¿Qué implicaciones tendrá esto ahora en referencia a linq? Es decir, ¿no podremos ahora usar una declaración como DBContext.Rank.Where(i => i.key == 1), y esta declaración no tendrá implementación en SQL y, por lo tanto, fallará?
David Harlow
Linq emitido contra este conjunto debe resolverse en la memoria. Si necesita emitir una cláusula WHERE sql diferente, debe incluirlos como parámetros o crear un script diferente.
E-Bat
Mi DbSet no tiene un método "FromSql". ¿Es esta una extensión que me falta?
Birwin
1
@birwin, necesita importar el espacio de nombres Microsoft.EntityFrameworkCore
E-Bat
20

Puede ejecutar sql sin procesar en EF Core: agregue esta clase a su proyecto. Esto le permitirá ejecutar SQL sin procesar y obtener los resultados sin tener que definir un POCO y un DBSet. Consulte https://github.com/aspnet/EntityFramework/issues/1862#issuecomment-220787464 para ver el ejemplo original.

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

Aquí hay un ejemplo de cómo 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]);
    }
}
Yehuda Goldenberg
fuente
18

Por ahora, hasta que haya algo nuevo de EFCore, usaría un comando y lo mapearía 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
         }
      }
  }

Intente SqlParameter para evitar la inyección de SQL.

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

FromSql no funciona con una consulta completa. Por ejemplo, si desea incluir una cláusula WHERE, se ignorará.

Algunos enlaces:

Ejecución de consultas SQL sin procesar mediante Entity Framework Core

Consultas SQL sin procesar

Enrique
fuente
7

En Core 2.1 puede hacer algo como esto:

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

y luego defina su procedimiento SQL, como:

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

De esta manera, el modelo de Ranks no se creará en su base de datos.

Ahora en su controlador / acción puede llamar:

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

De esta forma puede llamar a Procedimientos SQL sin formato.

RodrigoCampos
fuente
Los FromSqlparámetros podrían simplemente pasarse sin crear un SqlParameterobjeto: FromSql($"STORED_PROCEDURE {value1}, {value2}")o FromSql("STORED_PROCEDURE {0}, {1}", value1, value2)(se escaparán).
Majid
7

Puede usar esto (de 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);
        }
    }
}

Y el uso:

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

Agregar paquete Nuget - Microsoft.EntityFrameworkCore.Relational

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

Esto devolverá los números de fila como un int

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

Mohsin
fuente
3
Tenga en cuenta que esto solo devolverá el número de filas afectadas por el comando: stackoverflow.com/a/49861799/299756
kalyfe
Exactamente lo que necesito. Estoy usando Microsoft.EntityFrameworkCore 3.1.1 y no hay forma de ejecutar consultas RAW y SP. ¡Muchas gracias por esto!
Jaysonragasa
5

prueba esto: (crear método de extensión)

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

Uso:

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

mi modelo: (no en DbSet):

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

probado en .netCore 2.2 and 3.0.

Nota: esta solución tiene un rendimiento lento

AminRostami
fuente
Intente buscar PropertyInfo por nombre solo una vez para un primer registro solamente y cree una matriz de PropertyInfo [] por índices de columna para usar en los siguientes registros.
Petr Voborník
@AminRostami Buen trabajo
sebu
2

No apuntando directamente al escenario del OP, pero como he estado luchando con esto, me gustaría eliminar estos ex. métodos que facilitan la ejecución de SQL sin formato 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();
    }
  }
}
Shimmy Weitzhandler
fuente
1

Solía apuesto a esta restricción de derivación de Entity Framework Core.

IDbConnection.Query

está trabajando con una consulta SQL o un procedimiento almacenado con múltiples parámetros. Por cierto, es un poco más rápido (ver pruebas comparativas )

Dapper es fácil de aprender. Tomó 15 minutos escribir y ejecutar el procedimiento almacenado con parámetros. De todos modos, puede usar EF y Dapper. A continuación se muestra un ejemplo:

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


        }
}
Vladimir Lapenkov
fuente
0

También puede utilizar QueryFirst . Como Dapper, esto está totalmente fuera de EF. A diferencia de Dapper (o EF), no necesita mantener el POCO, edita su SQL SQL en un entorno real y se revalida continuamente contra la base de datos. Descargo de responsabilidad: soy el autor de QueryFirst.

bbsimonbb
fuente
0

Mi caso usó procedimiento almacenado en lugar de SQL sin formato

Creó una clase

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

Agregado a continuación en mi DbContextclase

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

Para ejecutar el procedimiento almacenado:

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

Esta solución se apoya en gran medida en la solución de @pius. Quería agregar la opción para admitir parámetros de consulta para ayudar a mitigar la inyección de SQL y también quería convertirlo en una extensión de DbContext DatabaseFacade para Entity Framework Core para hacerlo un poco más integrado.

Primero crea una nueva clase con la extensión:

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

}

Tenga en cuenta en lo anterior que "T" es el tipo para la devolución y "P" es el tipo de los parámetros de su consulta que variarán en función de si está utilizando MySql, Sql, etc.

A continuación mostraremos un ejemplo. Estoy usando la capacidad MySql EF Core, por lo que veremos cómo podemos usar la extensión genérica anterior con esta implementación de MySql más específica:

//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 consulta devolvería filas como:
"Ford", "Explorer", "Ford Explorer"
"Tesla", "Model X", "Tesla Model X"

El título de visualización no está definido como una columna de la base de datos, por lo que no sería parte del modelo EF Car de forma predeterminada. Me gusta este enfoque como una de las muchas posibles soluciones. Las otras respuestas en esta página hacen referencia a otras formas de abordar este problema con el decorador [NotMapped], que según su caso de uso podría ser el enfoque más apropiado.

Tenga en cuenta que el código en este ejemplo es obviamente más detallado de lo que debería ser, pero pensé que aclaraba el ejemplo.

dan-iel
fuente
-6

Con Entity Framework 6 puede ejecutar algo como a continuación

Crear clase modal como

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

Ejecute el comando Raw DQL SQl como se muestra a continuación:

var userList = datacontext.Database.SqlQuery<User>(@"SELECT u.Id ,fname , lname ,username FROM dbo.Users").ToList<User>();
Siddhartha
fuente