Establezca la ID y las propiedades calculadas en Entity Framework sin disparadores

Este artículo trata sobre lo siguiente:

Índice

    StoreGeneratedPattern

    El Entity Framework contiene una excelente funcionalidad de columnas de entidad generadas por el servidor, que está diseñado para determinar los valores de la clave principal en el lado de la base de datos, verificar el paralelismo, etc. Esto se hace mediante la personalización. StoreGeneratedPattern columnas de la parte de almacenamiento del modelo EF (SSDL) en Identity o Computed.

    Identidad

    En varias bases de datos (Microsoft SQL Server, MySQL, PostgreSQL, SQLite) StoreGeneratedPattern. El diseñador de EF determina la identidad de las columnas de clave principal cuando se crea el modelo en la base de datos y cuando estas columnas se incrementan automáticamente en la base de datos. Oracle no tiene una forma estándar de aumentar automáticamente la columna, por lo que en la base de datos los usuarios deben crear una secuencia y desencadenar ANTES DE INSERTAR, lo que determina el valor del incremento automático de la columna en función de la secuencia; cuando se crea un modelo, los usuarios deben establecer el valor StoreGeneratedPattern manualmente en el editor de modelos.

    Calculado

    En la mayoría de los casos, el soporte para esta funcionalidad implica escribir activadores de ACTUALIZACIÓN en una base de datos, lo que lleva tiempo y requiere conocimiento de un lenguaje de programación específico que no sea SQL, como PL/SQL en Oracle.

    Valor por defecto

    Para facilitar y acelerar el proceso de desarrollo, así como aumentar su flexibilidad, hemos proporcionado a los usuarios nuestros proveedores de EF Oráculo, mysql, postgresql y SQLite con una característica que en casos simples elimina la necesidad de escribir activadores INSERTAR y ACTUALIZAR y establecer un valor predeterminado para las columnas en la base de datos. Esto también puede ser útil si necesita, si es posible, utilizar objetos existentes en lugar de modificar la base de datos. Ahora puede asignar valores a una columna definiendo funciones de base de datos en los atributos DefaultValue de la columna en la parte de almacenamiento EF (SSDL).

    Si utiliza Entity Data Model Designer, deberá editar el modelo XML mediante el Editor XML. Tenga en cuenta que el atributo DefaultValue estándar se comprueba mediante la comprobación de EF y, por lo tanto, no se puede utilizar para llamar a la función de la base de datos. Por este motivo, hemos introducido un nuevo atributo personalizado devart: DefaultValue SSDL (si necesita editar manualmente el archivo EDMX, asegúrese de agregar el atributo xmlns: devart = ”http://devart.com/schemas/edml/ StorageSchemaExtensions / 1.0″ a la etiqueta de Schema SSDL). El atributo devart: DefaultValue no ejecuta la verificación de coherencia de tipos, por lo que puede usar una gama más amplia de valores predeterminados, como CURRENT_TIMESTAMP o MY_SEQUENCE.NEXTVAL.

    Si utiliza Desarrollador de la entidad Devartpodrá establecer el valor de DefaultValue en el constructor y almacenará correctamente este valor en los atributos DefaultValue o en devart: DefaultValue si es necesario.

    InsertNullBehavior

    Para utilizar esta funcionalidad, debe configurar el proveedor de EF. Para obtener más información sobre las funciones de configuración, consulte "Nuevo soporte de Entity Framework para proveedores de DotConnect"; para los fines de este artículo, consideraremos un pequeño ejemplo que muestra cómo configurar el comportamiento de procesamiento de DefaultValue. En este ejemplo, estamos tratando con un proveedor dotConnect para Oracle, pero el procedimiento es idéntico para MySQL, PostgreSQL y SQLite.

      var config = OracleEntityProviderConfig.Instance;
    
      config.DmlOptions.InsertNullBehaviour = InsertNullBehaviour.InsertDefaultOrNull;
      // or
      config.DmlOptions.InsertNullBehaviour = InsertNullBehaviour.InsertDefaultOrOmit;

    Se están configurando nuevas funciones en el aula. EntityProviderConfig. Esta clase está disponible en la compilación Devart.Data..Entidad. No olvide agregar la compilación Devart.Data..Entity.dll como referencia para la versión correspondiente de Entity Framework (el soporte para nuevas funciones está disponible para EF v1 y v4.x).
    Para obtener más información sobre las funciones de InsertNullBehavior, consulte aquí.

    Ejemplo

    Como ejemplo, usaremos una tabla en Oracle en la que queremos definir el comportamiento de las columnas creadas en la tienda, en el modelo, en lugar de crear disparadores. Para los propósitos de este ejemplo, también asumimos que ya tenemos una secuencia (MI_SECUENCIA) y una función de base de datos (MI_FUNCIÓN) que ahora podemos usar. Demostremos todas las posibilidades en un ejemplo.
    El siguiente es un script para crear una tabla:

    CREATE TABLE "Products" (
      ID NUMBER(9) PRIMARY KEY,
      "ProductName" VARCHAR2(160) NOT NULL,
      "Price" NUMBER(10, 2),
      "FunctionGeneratedValue" NUMBER NOT NULL,
      "ModifiedBy" VARCHAR2(30) NOT NULL,
      "LastModified" TIMESTAMP NOT NULL
    )

    Representación XML del objeto en el modelo de almacenamiento (SSDL):

      <EntityType Name="Products">
        <Key>
          <PropertyRef Name="ID" />
        </Key>
        <Property Name="ID" Type="int" Nullable="false" />
        <Property Name="ProductName" Type="VARCHAR2" Nullable="false" MaxLength="160" />
        <Property Name="Price" Type="double" />
        <Property Name="FunctionGeneratedValue" Type="decimal" Nullable="false" />
        <Property Name="ModifiedBy" Type="VARCHAR2" Nullable="false" MaxLength="30" />
        <Property Name="LastModified" Type="TIMESTAMP" Nullable="false" />
      </EntityType>

    Ahora cambiaremos el mapeo definiendo las siguientes reglas:

    • La columna ID, que es la clave principal, estará determinada por el valor de la secuencia MY_SEQUENCE en INSERT.
    • La columna "FunctionGeneratedValue" se definirá llamando a la función definida por el usuario MY_FUNCTION () en INSERT.
    • "Modificado por" se determinará a través de la función de base de datos del sistema del USUARIO en INSERTAR y ACTUALIZAR.
    • La columna "LastModified" se definirá a través de la función del sistema CURRENT_TIMESTAMP en INSERTAR y ACTUALIZAR. Esta columna se usará para verificar el paralelismo, por lo que debemos configurar ConcurrencyMode = "Fixed" para esta columna en el modelo conceptual.

    XML SSDL después del cambio se muestra a continuación:

      <EntityType Name="Products">
        <Key>
          <PropertyRef Name="ID" />
        </Key>
        <Property Name="ID" Type="int" Nullable="false" StoreGeneratedPattern="Identity" devart:DefaultValue="MY_SEQUENCE.NEXTVAL" />
        <Property Name="ProductName" Type="VARCHAR2" Nullable="false" MaxLength="50" />
        <Property Name="Price" Type="double" />
        <Property Name="FunctionGeneratedValue" Type="decimal" Nullable="false" StoreGeneratedPattern="Identity" devart:DefaultValue="MY_FUNCTION()" />
        <Property Name="ModifiedBy" Type="VARCHAR2" Nullable="false" MaxLength="30" StoreGeneratedPattern="Computed" DefaultValue="USER" />
        <Property Name="LastModified" Type="TIMESTAMP" Nullable="false" StoreGeneratedPattern="Computed" devart:DefaultValue="CURRENT_TIMESTAMP" />
      </EntityType>

    El siguiente es un ejemplo de código C#:

     
      // Here we turn on the monitoring of interaction with the Base de datos through  dbMonitor
      var mon = new Devart.Data.Oracle.OracleMonitor { IsActive = true };
    
      // Here we configure the EF-provider, so that the default values defined in the model are used 
      var config = OracleEntityProviderConfig.Instance;
      config.DmlOptions.InsertNullBehaviour = InsertNullBehaviour.InsertDefaultOrNull; // InsertNullBehaviour.InsertDefaultOrOmit;
    
      // Here we create the context and perform insert and update of the entity 
      using (var ctx = new Entities()) {
    
        Products product = new Products() {
          ProductName = "Gadget",
          Price = 220.25
        };
        ctx.Products.AddObject(product);
        ctx.SaveChanges(); // INSERT
    
        product.Price = 199.99;
        ctx.SaveChanges(); // UPDATE
      }

    Recomendamos usar Devart para monitorear las solicitudes enviadas al servidor monitor de base de datos, una herramienta gratuita compatible con los proveedores de Devart EF. Sin embargo, se recomienda usar este monitor solo durante el desarrollo y la depuración de la aplicación, ya que su uso provoca una caída en el rendimiento.
    El siguiente es el SQL creado en INSERT:

     
    DECLARE
      updatedRowid ROWID;
    BEGIN
    INSERT INTO "Products"(ID, "FunctionGeneratedValue", "ModifiedBy", "LastModified", "ProductName", "Price")
    VALUES (MY_SEQUENCE.NEXTVAL, MY_FUNCTION(), USER, CURRENT_TIMESTAMP, :p0, :p1)
    RETURNING ROWID INTO updatedRowid;
    OPEN :outParameter FOR SELECT ID, "FunctionGeneratedValue", "ModifiedBy", "LastModified" FROM "Products" WHERE ROWID = updatedRowid;
    END;

    El siguiente es el SQL creado durante la ACTUALIZACIÓN:

     
    DECLARE
      updatedRowid ROWID;
    BEGIN
    UPDATE "Products"
       SET "ModifiedBy" = USER, "LastModified" = CURRENT_TIMESTAMP, "Price" = :p0
     WHERE ID = :p1 AND "LastModified" = :p2
    RETURNING ROWID INTO updatedRowid;
    OPEN :outParameter FOR SELECT "ModifiedBy", "LastModified" FROM "Products" WHERE ROWID = updatedRowid;
    END;

    Conclusión

    Como hemos visto, esta característica es extremadamente fácil de usar. Si aún no está utilizando Entity Developer, cuya versión EF viene con nuestros proveedores de EF, piénselo, porque hace que cambiar el modelo de almacenamiento sea mucho más fácil y conveniente que un diseñador EDM estándar y, por lo tanto, una herramienta más adecuada para este propósito. . Además, no olvide vigilar el envío de SQL en la etapa de desarrollo para que pueda estar seguro de que todo funciona según lo previsto.

    Artículos de interés

    Subir