Consejos y trucos de Entity Framework, Parte 1

Este artículo abrirá 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.

Nuestra primera publicación consta de las siguientes preguntas de los usuarios sobre Entity Framework:

1. ¿Cómo proporcionar la fecha y hora actual para filtrar registros?

Problema:

Estoy tratando de filtrar los resultados en la consulta LINQ to Entities y mostrar todos los pedidos que son más antiguos que hoy. Creé dos consultas y cada una devuelve diferentes conjuntos de registros. Por ejemplo,

Esta consulta a veces devuelve resultados incorrectos:

var query = from c in db.Orders where c.OrderDate <= DateTime.Now select c;

La instrucción SQL correspondiente es la siguiente:

SELECT * FROM Orders WHERE OrderDate <= CURRENT_DATE

Esta consulta siempre funciona bien:

DateTime date = DateTime.Now;
var query = from c in db.Orders where c.OrderDate <= date select c;

La instrucción SQL correspondiente es la siguiente:

SELECT * FROM Orders WHERE OrderDate <= :p0

El : p0 el parámetro está relacionado con el valor actual de la fecha y la hora, por ejemplo, '10/06/2010'.

¿Podría explicar las razones de tal comportamiento? ¿Estoy haciendo algo mal?

Respuesta:

Si tiene una diferencia entre las fechas del servidor y la máquina local, es mejor usar el parámetro local en sus consultas de LINQ to Entities. Esto asegura que usará los valores de su máquina local.

Nota: Esta situación no es un problema o un error. Cuándo Fecha y hora utilizado como parámetro de la consulta LINQ to Entities, se asignará a una función que devuelve el valor de la fecha y hora actuales en formato de servidor. Si pasa una variable local como parámetro de consulta a LINQ to Entities, la fecha y la hora actuales se convertirán al formato de máquina local.

2. ¿Cómo puedo usar tipos XML de tablas de Oracle en el modelo de Entity Framework?

Problema:

Estoy usando Entity Framework e intento acceder a una tabla de Oracle que contiene un campo de tipo de datos XMLTYPE. Al leer los datos de la tabla, obtengo la siguiente excepción: "ORA-03115 tipo o vista de datos de red no admitidos". ¿Puedo usar XMLTYPE en Entity Framework con dotConnect para Oracle?

Solución:

Puede usar el tipo XML directamente solo en modo OCI porque el modo directo tiene una serie de limitaciones. Por favor mira Uso del modo directo el tema de nuestra documentación para obtener detalles sobre las restricciones del modo directo.
Puede utilizar Oracle CLOB como solución alternativa. Para hacer esto, deberá realizar los siguientes cambios en el archivo .edmx (o .edml):

1. SSDL. Aquí debe agregar DefiningQuery a su tabla:

<EntitySet Name="XML_TYPEs" EntityType= "DataSourceModel1.Store.XML_TYPE"
store:Type =  "Views">
  <DefiningQuery>
    SELECT
      "Extent1".ID AS ID,
      "Extent1".XMLFIELD.GetClobVal() AS XMLFIELD
      FROM SCOTT.XML_TYPE "Extent1"
  </DefiningQuery>
</EntitySet>

También agregue una definición de las propiedades de su tabla:

<EntityType Name="XML_TYPE">
   <Key>
       <PropertyRef Name="ID" />
   </Key>
   <Property Name="ID" Type="decimal" Nullable="false" />
   <Property Name="XMLFIELD" Type="XMLTYPE" />
</EntityType>

2. Parte de CSDL. Aquí es suficiente declarar una clase y sus propiedades:

<EntitySet Name="XmlTypes" EntityType="DataSourceModel1.XmlType" />
    <EntityType Name="XmlType">
       <Key>
         <PropertyRef Name=&Quot;Id" />
       </Key>
       <Property Name="Id" Type="Decimal" Nullable="false" />
       <Property Name="Xmlfield" Type="String" />
    </EntityType>
</EntitySet>

3. Parte de MSL. Simplemente muestre la pantalla:

<EntitySetMapping Name="XmlTypes">
   <EntityTypeMapping TypeName="DataSourceModel1.XmlType">
      <MappingFragment StoreEntitySet="XML_TYPEs">
        <ScalarProperty Name="Id" ColumnName="ID" />
        <ScalarProperty Name="Xmlfield" ColumnName="XMLFIELD" />
      </MappingFragment>
   </EntityTypeMapping>
</EntitySetMapping>

Estas operaciones le permiten leer columnas XMLTYPE en su código. Para guardar objetos XMLTYPE en una base de datos, deberá escribir un conjunto de procedimientos guardados (para insertar, actualizar y eliminar) y mostrar estos procedimientos como acciones Insertar/Actualizar/Eliminar en el formulario Personalizar comportamiento.

3. ¿El tipo ORA_ROWSCN es útil para el procesamiento paralelo en Entity Framework?

Problema:

¿Puedo usar la columna Oracle ORA_ROWSCN para fines de control paralelo en Entity Framework?

Solución:

De hecho, la columna ORA_ROWSCN no es muy útil en esta situación. El valor de esta columna se actualiza solo después de corregir la transacción que ocurre al final de todo Guardar cambios ()realizado.

En caso de que el primer usuario realice la inserción (ORA_ROWSCN será cero después de esta operación), luego actualiza el objeto desde la base de datos (ObjectContext.Actualizar ()) y realiza la actualización, sin problemas. Pero en caso de que el primer usuario quiera guardar los cambios y luego actualizar los valores insertados por él (sin actualizarlos explícitamente), puede ocurrir un error de paralelismo innecesario. El mismo problema ocurrirá si este usuario desea realizar dos actualizaciones consecutivas separadas por una llamada SaveChanges. Tenga en cuenta que el valor antiguo de ORA_ROWSCN se leerá después de la primera actualización.

En caso de que el segundo usuario actualice el registro que acaba de insertar el primero, todo irá sobre ruedas. Por lo tanto, la única forma posible de actualizar el valor de esta columna es actualizar todo el objeto (recuperarlo de la base de datos), lo que parece redundante.

4. ¿Qué es un operador de "aplicación externa" y por qué no se admite en las declaraciones de Entity Framework?

Problema:

yo suelo primero o predeterminado con la condición por primera vez.
Probé algunas permutaciones. Siempre con el mismo resultado: fracaso.

Tengo las siguientes tablas:

  • Vacantes (lista de vacantes)
  • Nombres (lista de nombres capaces de realizar tareas)
  • JobNames (lista de nombres relacionados con un trabajo específico)

Todas las vacantes tienen al menos un nombre asociado, por lo que para cada línea en Trabajos hay al menos una línea en JobNames.

Hay un nombre principal (persona responsable) para cada trabajo. Los nombres de trabajo tienen columnas:

  • Apellido
  • Nombre
  • Responsable

Para cada trabajo hay una línea en Jobnames en la que el indicador IsResponsible se establece en verdadero.

Hay una línea en las vacantes y una línea en JobNames, y el indicador IsResponsible se establece en verdadero.

Se utilizó Devart para PostgreSQL para construir un modelo de entidad para consultas.

Quiero que el nombre de la persona a cargo del trabajo esté en la lista de vacantes.

Código de solicitud:

Surname = Jobs.JobNames.FirstOrDefault().Names.Surname;

Esto funciona, pero no puedo garantizar que se devuelva el nombre de la persona responsable. Mirando ejemplos en línea para la sintaxis que asumí:

Surname = Jobs.JobNames.FirstOrDefault(n => n.IsResponsible == true).Names.Surname;

A veces no funciona con un error:

base {System.Data.EntityException} 
  = {"An error occurred while preparing the command definition. 
     See the inner exception for details."}

InnerException = {“ACCESORIO EXTERNO no compatible con PostgreSQL”}

¿Significa esto que el problema es con Postgres y no puedo hacer eso?
¿Hay algún problema con la interfaz de Devart y, de ser así, habrá una solución?
¿Hay una solución al problema?

Solución:

La declaración OUTER APPLY le permite llamar a una función con un valor de tabla para cada fila devuelta por una expresión de una tabla de consulta externa. Solo se admite en Microsot SQL Server 2005 y superior, pero la consulta de Entity Framework en código C # se transforma en un árbol de expresión con código de Microsoft, y solo después de esta conversión generamos una consulta SQL específica del proveedor. A veces, la declaración OUTER APPLY se incluye en su consulta SQL, incluso si usa otros servidores de bases de datos. Esta es la causa del error descrito en este comunicado. Agregamos Excepción no admitida en el caso de Aplicar exterior en el árbol de expresión.


Este material se mejorará cuando nuestro equipo de soporte resuelva nuevas solicitudes. Esperamos que este artículo le sea útil y lo ayude a usar Entity Framework.

Artículos de interés

Subir