Pregunta

De modo que el principal programa en C#.La inserción de nuevos registros en una tabla de base de datos de VFP.Se estaba tomando demasiado tiempo para generar el siguiente IDENTIFICADOR para el registro a través de

select max(id)+1 from table

, por lo que poner ese código en una compilación de dll en VFP y estoy llamando a ese objeto COM a través de C#.

El objeto COM devuelve el ID nuevo en alrededor de 250 ms.A continuación, sólo hacer una actualización a través de OLEDB.El problema que estoy teniendo es que después de que el objeto COM devuelve el recién ID insertado, no puedo encontrar inmediatamente desde C# a través de la OLEDB

select id form  table where id = *newlyReturnedID*

devuelve 0 filas de atrás.Si tengo que esperar un tiempo desconocido período de la consulta devolverá 1 fila.Sólo puedo suponer que se devuelve 0 filas inmediatamente porque aún no se ha añadir la de nuevo cuño de IDENTIFICACIÓN en el índice y por lo tanto el select no se puede encontrar.

Tiene alguien alguna vez algo similar?Si es así, ¿cómo manejarlo?

DD

¿Fue útil?

Solución

Advertencia:el código es erróneo, en un entorno multi-usuario.Dos personas se pudo ejecutar la consulta en el mismo tiempo y obtener el mismo ID.Uno de ellos se producirá un error en la INSERCIÓN si la columna tiene un principal o clave candidata, que es una de las mejores prácticas para los campos de clave.

Mi recomendación es tener el IDENTIFICADOR de ser un auto-incrementar campo entero (yo no soy un fan de ellos), o mejor aún, crear una tabla de claves.Cada registro de la tabla es una tabla que presenta las claves asignadas.Yo uso el de una estructura similar a esta:

       Structure for: countergenerator.dbf
       Database Name: conferencereg.dbc
     Long table name: countergenerator
   Number of records: 0
        Last updated: 11/08/2008
Memo file block size: 64
           Code Page: 1252
          Table Type: Visual FoxPro Table

Field  Name                  Type                 Size   Nulls       Next       Step  Default  
----------------------------------------------------------------------------------------------------------------
    1  ccountergenerator_pk  Character            36         N                        guid(36)  
    2  ckey                  Character (Binary)   50         Y                          
    3  ivalue                Integer               4         Y                          
    4  mnote                 Memo                  4         Y                        "Automatically created"  
    5  cuserid               Character            30         Y                        
    6  tupdated              DateTime              8         Y                        DATETIME()  

Index Tags: 
1. Tag Name: PRIMARY
 - Type: primary
 - Key Expression: ccountergenerator_pk
 - Filter: (nothing)
 - Order: ascending
 - Collate Sequence: machine

2. Tag Name: CKEY
 - Type: regular
 - Key Expression: lower(ckey)
 - Filter: (nothing)
 - Order: ascending
 - Collate Sequence: machine

Ahora el código para el procedimiento almacenado en el DBC (o en otro programa) es este:

FUNCIÓN NextCounter(tcAlias)

LOCAL lcAlias, ;lnNextValue, ;lnOldReprocess, ;lnOldArea

lnOldArea = SELECCIONAR()

SI LOS PARÁMETROS() <1 lcAlias = ALIAS()

SI CURSORGETPROP("SOURCETYPE") = DB_SRCLOCALVIEW *-- Intento de obtener la tabla de base de lcAlias = MENOR(CURSORGETPROP("TABLAS")) lcAlias = SUBSTR(lcAlias, EN("!", lcAlias) + 1) ENDIF Otra COSA lcAlias = MENOR(tcAlias) ENDIF

lnOrderNumber = 0 lnOldReprocess = SET('volver a procesar')

*-- Bloqueo hasta que el usuario pulsa Esc SET REPROCESS AUTOMÁTICO

SI!!!Se UTILIZAN("countergenerator") USO EventManagement!countergenerator EN 0 COMPARTIDA ALIAS countergenerator ENDIF

SELECCIONE countergenerator

SI BUSCAN(INFERIOR(lcAlias), "countergenerator", "ckey") SI RLOCK() lnNextValue = countergenerator.iValue REEMPLAZAR countergenerator.iValue CON countergenerator.iValue + 1 DESBLOQUEAR ENDIF Otra COSA * Crear el nuevo registro con el valor inicial.ANEXAR en BLANCO EN countergenerator SCATTER MEMVAR MEMO m.cKey = MENOR(lcAlias) m.iValue = 1 m.mNote = "creado Automáticamente por el procedimiento almacenado." m.tUpdated = DATETIME() SE REÚNEN MEMVAR MEMO

SI RLOCK() lnNextValue = countergenerator.iValue REEMPLAZAR countergenerator.iValue CON countergenerator.iValue + 1 DESBLOQUEAR ENDIF ENDIF

SELECCIONE (lnOldArea) CONJUNTO de volver a procesar A lnOldReprocess

VOLVER lnNextValue ENDFUNC

El RLOCK() se asegura de que no hay disputas por los registros y es lo suficientemente rápido como para no tener cuello de botella en el proceso.Esta es la forma más segura que el enfoque que está tomando actualmente.

Rick Schummer
VFP MVP

Otros consejos

FLUSH sus áreas de trabajo .

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top