Consejos y trucos de Entity Framework, Parte 2

En este artículo, continuamos una serie de publicaciones sobre situaciones no triviales que enfrentan nuestros usuarios. Algunas de estas situaciones son limitaciones de las plataformas utilizadas y otras simplemente requieren un enfoque no estándar para resolver el problema.

En este artículo, abordamos los siguientes temas:

1. ¿Cómo puedo ejecutar mi propio SQL utilizando Entity Framework?

Problema:

Parece que no puedo usar CreateQuery. Tengo el siguiente código:

using (Entities ent = new Entities())
{
        var results = ent.CreateQuery<PRODUCTS>("SELECT * FROM "Products"");

        foreach (var row in results)
        {
             Console.WriteLine("id: " + row.ID.ToString());
        }
}

Esto conduce a un error:

"La sintaxis de consulta no es válida, junto al término '*', línea 1, columna 11".

¿Qué debo usar para ejecutar SQL nativo?

Solución:

El método CreateQuery acepta una consulta Entity SQL, no una consulta SQL.

Puede utilizar el método ObjectContext.ExecuteStoreQuery para ejecutar una consulta SQL. Tenga en cuenta que solo está disponible en Entity Framework v4.

Hay otra forma de ejecutar su propio SQL tanto en Entity Framework v1 como en Entity Framework v4. Puede utilizar la propiedad StoreConnection del objeto ObjectContext.Connection. Aquí hay un ejemplo para Oracle:

using (OracleConnection connection 
 = (entities.Connection as EntityConnection).StoreConnection as OracleConnection) 
{
      OracleCommand command 
        = new OracleCommand("SELECT * FROM "Products"", connection);

      connection.Open();
      OracleDataReader reader = command.ExecuteReader();

      //Materialize your query results here
}

2. ¿Cómo puedo usar objetos de seguimiento automático (STE) o POCO en el modelo de entidad de Devart?

Problema:

Estoy usando EF 4.0 en la parte superior de su proveedor dotConnect para Oracle. Quiero usar objetos de seguimiento automático. ¿Puedo cambiar el nombre? edml presentar en edmx y usar STE con este archivo? ¿Puedo hacer lo mismo en el caso de utilizar instalaciones POCO?

Solución:

El modelo de Devart tiene una estructura similar al modelo de Microsoft. Pero hay algunos ajustes. No debería haber problemas para cambiar la extensión (edml -> edmx).

Hay otro enfoque para usar STE o POCO con .edml Archivo:

  1. Ir% Archivos de programa% Microsoft Visual Studio 10.0Common7IDEExtensionsMicrosoftEntity Framework ToolsTemplatesIncludesEF.Utility.CS.ttinclude
  2. Cambio
    if (extension.Equals(".edmx", StringComparison.InvariantCultureIgnoreCase))

    oficina

    if(extension.Equals(".edmx", StringComparison.InvariantCultureIgnoreCase)
    ||
    extension.Equals(".edml", StringComparison.InvariantCultureIgnoreCase))
  3. Guarda el archivo

En caso de que esté utilizando VB.NET, debe realizar estas operaciones utilizando un archivo

% Archivos de programa% Microsoft Visual Studio 10.0Common7IDEExtensionsMicrosoftEntity Framework ToolsTemplatesIncludesEF.Utility.VB.ttinclude Archivo. Cambiar la siguiente línea

If  (extension.Equals(".edmx", StringComparison.InvariantCultureIgnoreCase))

oficina

If (extension.Equals(".edmx", StringComparison.InvariantCultureIgnoreCase)
Or
extension.Equals(".edml", StringComparison.InvariantCultureIgnoreCase))

Planeamos agregar compatibilidad con las instalaciones de autoseguimiento y POCO en uno de los ensamblajes futuros.

3. ¿Cómo puedo usar los procedimientos de Oracle guardados con un parámetro booleano en Entity Framework?

Problema:

Estoy tratando de ejecutar un procedimiento almacenado con el parámetro PL/SQL BOOLEAN en Entity Framework, pero siempre obtengo "ORA-06550: PLS-00306: número incorrecto o tipos de argumentos al llamar a 'EF_BOOLEAN_SP'".

Esto es un error, ¿hay alguna solución para esta situación?

Solución:

Los parámetros PL/SQL BOOLEAN no se admiten directamente en Entity Framework, pero en este caso hay una solución. Estos son los pasos para resolver el problema:

  1. Agregue un procedimiento al modelo de entidad Devart (puede realizar todas las acciones con el modelo de datos de entidad ADO.NET, pero estas acciones deben realizarse en XML utilizando el editor XML)
  2. Cambie el tipo de parámetro PL/SQL BOOLEAN a bool
  3. Edite CommandText para este procedimiento. Escriba un bloque PL/SQL simple que llame al procedimiento. Asegúrese de pasar los parámetros y convertir los parámetros requeridos de NUMBER a PL/SQL BOOLEAN usando la función SYS.DIUTIL.INT_TO_BOOL Aquí hay un ejemplo simple de XML: Texto antes de cambios:
    <Function Name=" EF_BOOLEAN_SP" IsComposable="false" 
    BuiltIn="false" Aggregate="false" NiladicFunction="false" ParameterTypeSemantics="AllowImplicitConversion" 
    Schema="TEST" StoreFunctionName="EF_BOOLEAN_SP">
              <Parameter Name="PK" Type="int64" Mode="In" />
              <Parameter Name="FLAG" Type="PL/SQL BOOLEAN" Mode="In" />
    </Function>

    Texto después de los cambios:

    <Function Name=" EF_BOOLEAN_SP" IsComposable="false" 
    BuiltIn="false" Aggregate="false" NiladicFunction="false" ParameterTypeSemantics="AllowImplicitConversion">
          <CommandText>
             BEGIN 
                 EF_BOOLEAN_SP(:PK, SYS.DIUTIL.INT_TO_BOOL(:FLAG));
             END;
          </CommandText>
          <Parameter Name="PK" Type="int64" Mode="In" />
          <Parameter Name="FLAG" Type="bool" Mode="In" />
    </Function>

4. ¿Cómo trabajar con UNION en Entity Framework?

Problema:

Creé la siguiente combinación de dos consultas:

string productName  = "Spotlight on Britain's economy";
var query1 = context.Products.Where(t => t.Productname == productName);

productName = "Carroll Lewis. Alice'sventures in Wonderland ";
var query2 = context.Products.Where(t => t.Productname == productName);

var resultQuery = query1.Union(query2);
var ResultSets = resultQuery.ToList();

Por alguna razón, solo obtengo un resultado: un libro de Lewis Carroll. ¿Es un comportamiento deliberado o un error?

Solución:

Este es un comportamiento deliberado. La razón de esto es la ejecución retrasada. La materialización real de query1 y query2 ocurre solo en la siguiente línea:

var ResultSets = resultQuery.ToList();

En este punto, también se pasan los valores de los parámetros (productName apunta al libro de Lewis Carroll), por lo que los resultados de query1 y query2 son los mismos.
La solución es utilizar diferentes variables para los parámetros o materializar la consulta inmediatamente después de asignar el valor del parámetro.

En el primer caso, cambie su código de la siguiente manera:

string productName  = "Spotlight on Britain's economy";
var query1 = context.Products.Where(t => t.Productname == productName);

string productName2 = "Carroll Lewis. Alice'sventures in Wonderland ";
var query2 = context.Products.Where(t => t.Productname == productName2);

var resultQuery = query1.Union(query2);
var ResultSets = resultQuery.ToList();

En este caso, la instrucción UNION se traduce como parte de la solicitud LINQ to Entities.

En el segundo caso, ambas solicitudes se materializan:

string productName  = "Spotlight on Britain's economy";
var query1 = context.Products.Where(t => t.Productname == productName);
query1.ToList();

productName = "Carroll Lewis. Alice'sventures in Wonderland ";
var query2 = context.Products.Where(t => t.Productname == productName);
query2.ToList();

var resultSet = query1.Union(query2);

En este caso, ambas listas se materializan antes de la aplicación de UNION. Por lo tanto, no hay necesidad de materializar la UNION en sí, se realiza como una operación LINQ to Objects.


Esperamos que este material le resulte útil. Por favor dé su opinión y sugerencias en los comentarios al artículo.

Artículos de interés

Subir