2009-05-27 18 views
64

Estoy tratando de buscar un campo XML dentro de una tabla, Esto no es compatible con EF.¿Es posible ejecutar sql nativo con entity framework?

¿Sin usar Ado.net puro es posible tener soporte SQL nativo con EF?

+0

Por favor, aclare su pregunta. Cuando pregunta por "soporte SQL nativo", ¿quiere decir más que "soporte para columnas XML"? ¿A qué más te refieres? Además, ¿qué problema tenías con la columna XML? ¿Simplemente no entró en la entidad o hubo un problema cuando trataste de usarla? Además, indique qué versión estaba usando? 2008, 2008 SP1, 2010 CTP o Beta 1? –

Respuesta

71

Para .NET Framework versión 4 y superior: use ObjectContext.ExecuteStoreCommand() si su consulta no arroja ningún resultado, y use ObjectContext.ExecuteStoreQuery si su consulta arroja resultados.

Para versiones anteriores de .NET Framework, aquí hay una muestra que ilustra qué hacer. Reemplace ExecuteNonQuery() según sea necesario si su consulta arroja resultados.

static void ExecuteSql(ObjectContext c, string sql) 
{ 
    var entityConnection = (System.Data.EntityClient.EntityConnection)c.Connection; 
    DbConnection conn = entityConnection.StoreConnection; 
    ConnectionState initialState = conn.State; 
    try 
    { 
     if (initialState != ConnectionState.Open) 
      conn.Open(); // open connection if not already open 
     using (DbCommand cmd = conn.CreateCommand()) 
     { 
      cmd.CommandText = sql; 
      cmd.ExecuteNonQuery(); 
     } 
    } 
    finally 
    { 
     if (initialState != ConnectionState.Open) 
      conn.Close(); // only close connection if not initially open 
    } 
} 
+38

Esta respuesta no está actualizada. Ver esta publicación http://geekswithblogs.net/rgupta/archive/2010/06/23/entity-framework-v4-ndash-tips-and-tricks.aspx. Puede ejecutar Sql directamente desde el marco de la entidad sin envoltorio requerido utilizando ** ExecuteStoreCommand ** o ** ExecuteStoreQuery ** directamente desde la instancia de la entidad. –

+9

Tenga en cuenta que esos métodos no son compatibles con DbContext, sin embargo, hay Database.ExecuteSqlCommand() o Database.SqlQuery . – nicodemus13

+1

@ user297691 - Actualicé la respuesta con nueva información. ¡Gracias! –

2
public class RaptorRepository<T> 
    where T : class 
{ 
    public RaptorRepository() 
     : this(new RaptorCoreEntities()) 
    { 
    } 

    public RaptorRepository(ObjectContext repositoryContext) 
    { 
     _repositoryContext = repositoryContext ?? new RaptorCoreEntities(); 
     _objectSet = repositoryContext.CreateObjectSet<T>(); 
    } 

    private ObjectContext _repositoryContext; 
    private ObjectSet<T> _objectSet; 
    public ObjectSet<T> ObjectSet 
    { 
     get 
     { 
      return _objectSet; 
     } 
    } 


    public void DeleteAll() 
    { 
     _repositoryContext 
      .ExecuteStoreCommand("DELETE " + _objectSet.EntitySet.ElementType.Name); 
    } 
} 
16

Desde .NET 4 se puede utilizar ExecuteStoreQuery método:

var list = myDBEntities.ExecuteStoreQuery<MyClass>(MyClass.sql); 

donde myDBEntities se hereda del ObjectContext.

class MyClass 
{ 
    /* You can change query to more complicated, e.g. with joins */ 
    public const string sql = @"select [MyTable].[MyField] from [MyTable]"; 
    public string MyField { get; set; } 
} 

en cuenta que MiTabla es real nombre de la tabla, no la clase de EF.

+1

Del comentario a continuación, context.Database.SqlQuery funciona en EF5 – Sameer

23

Utilizando Entity Framework 5.0 puede usar ExecuteSqlCommand para ejecutar declaraciones SQL de múltiples líneas/múltiples comandos. De esta manera, no necesitará proporcionar ningún objeto de respaldo para almacenar el valor devuelto, ya que el método devuelve un int (el resultado devuelto por la base de datos después de ejecutar el comando).

muestra:

context.Database.ExecuteSqlCommand(@ 
"-- Script Date: 10/1/2012 3:34 PM - Generated by ExportSqlCe version 3.5.2.18 
SET IDENTITY_INSERT [Students] ON; 

INSERT INTO [Students] ([StudentId],[FirstName],[LastName],[BirthDate],[Address],[Neighborhood],[City],[State],[Phone],[MobilePhone],[Email],[Enrollment],[Gender],[Status]) VALUES (12,N'First Name',N'SecondName',{ts '1988-03-02 00:00:00.000'},N'RUA 19 A, 60',N'MORADA DO VALE',N'BARRA DO PIRAÍ',N'Rio de Janeiro',N'3346-7125',NULL,NULL,{ts '2011-06-04 21:25:26.000'},2,1); 

INSERT INTO [Students] ([StudentId],[FirstName],[LastName],[BirthDate],[Address],[Neighborhood],[City],[State],[Phone],[MobilePhone],[Email],[Enrollment],[Gender],[Status]) VALUES (13,N'FirstName',N'LastName',{ts '1976-04-12 00:00:00.000'},N'RUA 201, 2231',N'RECANTO FELIZ',N'BARRA DO PIRAÍ',N'Rio de Janeiro',N'3341-6892',NULL,NULL,{ts '2011-06-04 21:38:38.000'},2,1); 
"); 

Para más información sobre esto, echar un vistazo aquí: Entity Framework Code First: Executing SQL files on database creation

17

Para Entity Framework 5 uso context.Database.SqlQuery.

Y para Entity Framework 4 uso context.ExecuteStoreQuery el siguiente código:

public string BuyerSequenceNumberMax(int buyerId) 
    { 
     string sequenceMaxQuery = "SELECT TOP(1) btitosal.BuyerSequenceNumber FROM BuyerTakenItemToSale btitosal " + 
            "WHERE btitosal.BuyerID = " + buyerId + 
            "ORDER BY CONVERT(INT,SUBSTRING(btitosal.BuyerSequenceNumber,7, LEN(btitosal.BuyerSequenceNumber))) DESC"; 

     var sequenceQueryResult = context.Database.SqlQuery<string>(sequenceMaxQuery).FirstOrDefault(); 

     string buyerSequenceNumber = string.Empty; 

     if (sequenceQueryResult != null) 
     { 
      buyerSequenceNumber = sequenceQueryResult.ToString(); 
     } 

     return buyerSequenceNumber; 
    } 

para devolver una lista utilice el siguiente código:

public List<PanelSerialList> PanelSerialByLocationAndStock(string locationCode, byte storeLocation, string itemCategory, string itemCapacity, byte agreementType, string packageCode) 
{ 
     string panelSerialByLocationAndStockQuery = "SELECT isws.ItemSerialNo, im.ItemModel " + 
     "FROM Inv_ItemMaster im " + 
     "INNER JOIN " + 
     "Inv_ItemStockWithSerialNoByLocation isws " + 
     " ON im.ItemCode = isws.ItemCode " + 
     "  WHERE isws.LocationCode = '" + locationCode + "' AND " + 
     " isws.StoreLocation = " + storeLocation + " AND " + 
     " isws.IsAvailableInStore = 1 AND " + 
     " im.ItemCapacity = '" + itemCapacity + "' AND " + 
     " isws.ItemSerialNo NOT IN (" + 
     "   Select sp.PanelSerialNo From Special_SpecialPackagePriceForResale sp " + 
     "   Where sp.PackageCode = '" + packageCode + "')"; 


    return context.Database.SqlQuery<PanelSerialList>(panelSerialByLocationAndStockQuery).ToList(); 


} 
3

Debe ser sencillo

using (var context = new MyDBEntities()) 
{ 
    var m = context.ExecuteStoreQuery<MyDataObject>("Select * from Person", string.Empty); 
    //Do anything you wonna do with 
    MessageBox.Show(m.Count().ToString()); 
} 
0

¿Qué decimos sobre todo esto en 2017? Las consultas de 80k sugieren que ejecutar una solicitud SQL en EF es algo que mucha gente quiere hacer. ¿Pero por qué? ¿Para qué beneficio?

Justin, un gurú con 20 veces mi reputación, en la respuesta aceptada nos da un método estático que se ve línea por línea como el código ADO equivalente. Asegúrese de copiarlo bien porque hay algunas sutilezas para no equivocarse. Y está obligado a concatenar su consulta con sus parámetros de tiempo de ejecución ya que no hay ninguna disposición para los parámetros adecuados.De modo que todos los usuarios de este método construirán su SQL con métodos de cadena (frágiles, no comprobables, inyección de SQL) y ninguno de ellos será una prueba unitaria.

Las otras respuestas tienen las mismas fallas, solo que más. SQL enterrado entre comillas dobles. Las oportunidades de inyección de SQL abundantemente dispersas. Compañeros estimados, este es un comportamiento absolutamente salvaje. Si se generara C#, habría una guerra de llamas. Ni siquiera aceptamos generar HTML de esta manera, pero de alguna manera está bien para SQL. Sé que los parámetros de consulta no fueron el tema de la pregunta, pero copiamos y reutilizamos lo que vemos, y las respuestas aquí son tanto modelos como testimonios de lo que la gente está haciendo.

¿EF fundió nuestros cerebros? EF no quiere que uses SQL, entonces, ¿por qué usar EF para hacer SQL?

Querer usar SQL para hablar con una base de datos relacional es un impulso saludable y normal en los adultos. QueryFirst muestra cómo esto podría hacerse de manera inteligente, su sql en archivo .sql, validado mientras escribe, con intellisense para tablas y columnas. El contenedor C# es generado por la herramienta, por lo que sus consultas se vuelven visibles en el código, con intellisense para sus entradas y resultados. Tipificación fuerte de extremo a extremo, sin tener que preocuparse por un tipo. No es necesario recordar nunca un nombre de columna, o su índice. Y hay muchos otros beneficios ... La tentación de concatenar es eliminado. La posibilidad de mal manejo de sus conexiones también. Todas sus consultas y el código que accede a ellas se prueban continuamente en la integración contra su DB de desarrollo. Los cambios de esquema en su base de datos emergente como errores de compilación en su aplicación. Incluso generamos un método de auto prueba en el contenedor, por lo que puede probar nuevas versiones de su aplicación contra bases de datos de producción existentes, en lugar de esperar a que suene el teléfono. ¿Alguien todavía necesita convencerse?

Descargo de responsabilidad: Escribí QueryFirst :-)

Cuestiones relacionadas