2012-01-11 12 views
5

Necesito modificar el esquema de una base de datos MS Acess (.mdb) mediante el código.¿Es posible modificar un esquema de base de datos de MS Access usando ADO.NET?

Dado que las declaraciones del motor de jet DDL (ALTER TABLE, etc.) son muy poco documentada, yo prefiero usar algún tipo de biblioteca de objetos como DAO (myDatabase.TableDefs("myTable").Fields.Append(myNewField)) o ADOX (myCatalog.Tables("myTable").Columns.Append(myNewField)) o SMO (que sólo está disponible para SQL Server, sintaxis similar, ya se entiende).

¿Hay algo similar como ADOX para ADO.NET o estoy atascado con el uso de sentencias DDL o haciendo referencia a las antiguas bibliotecas DAO/ADOX?

+1

¿Qué quiere decir que está [mal documentado] (http://msdn.microsoft.com/en-us/library/bb267262%28v=office.12%29.aspx)? ¿Qué enunciado no está claro para ti? De todos modos, puedes usar ADOX en .NET. Por ejemplo, vea [Cómo crear una base de datos de Access usando ADOX y Visual C# .NET] (http://support.microsoft.com/kb/317881). – RedFilter

+0

Gracias por el enlace, parece que la documentación ha sido ampliamente mejorada en las últimas versiones de Access. Aún así, un ejemplo: la página ALTER TABLE no contiene una lista de tipos de datos válidos; no está del todo claro (de la documentación), por ejemplo, cómo crearía un nuevo decimal con precisión X y escala Y. Mientras tanto, he encontrado una tabla de palabras clave de ese tipo (está vinculada en la sección de comentarios del usuario). de la [documentación de CREATE TABLE] (http://msdn.microsoft.com/en-us/library/bb177893.aspx)), pero eso está lejos de la calidad de, por ejemplo, el SQL Server BOL. – Heinzi

+2

Ah, y otra razón por la que administrar los esquemas de acceso a través de DDL no es una buena idea: [Los conjuntos de filas de esquema están rotos.] (Http://social.msdn.microsoft.com/Forums/eu/adodotnetdataproviders/thread/58a17c99-0b23 -4341-a274-db2dd91e0886) Acabo de enterarme por las malas que ni las tablas de esquema OLE DB ni las tablas de esquema ODBC devuelven los valores IS_NULLABLE correctos para los campos de acceso. Parece que la * única * forma confiable de verificar si un campo de Acceso es anulable es usar ** DAO ** y verificar si 'myField.Required'. ¿Qué tan patético es eso? Tener que agregar una referencia DAO a un proyecto .net en 2012 ... – Heinzi

Respuesta

1

He tenido un éxito decente con declaraciones ddl directas. A su derecha, la sintaxis requiere una pizca de búsqueda en Google para desentrañar, pero he estado manejando las actualizaciones de una base de datos local de esta manera por un tiempo. ¿Hay alguna actualización específica con la que tengas problemas? Básicamente escribí algunas funciones de ayuda para verificar la estructura de una tabla y anexar campos si es necesario.

public bool doesFieldExist(string table, string field) 
    { 
     bool ret = false; 
     try 
     { 
      if (!openRouteCon()) 
      { 
       throw new Exception("Could not open Route DB"); 
      } 
      DataTable tb = new DataTable(); 
      string sql = "select top 1 * from " + table; 
      OleDbDataAdapter da = new OleDbDataAdapter(sql, routedbcon); 
      da.Fill(tb); 
      if (tb.Columns.IndexOf(field) > -1) 
      { 
       ret = true; 
      } 

      tb.Dispose(); 


     } 
     catch (Exception ex) 
     { 
      log.Debug("Check for field:" + table + "." + field + ex.Message); 
     } 

     return ret; 
    } 


    public bool checkAndAddColumn(string t, string f, string typ, string def = null) 
    { 

     // Update RouteMeta if needed. 
     if (!doesFieldExist(t, f)) 
     { 
      string sql; 
      if (def == null) 
      { 
       sql = String.Format("ALTER TABLE {0} ADD COLUMN {1} {2} ", t, f, typ); 
      } 
      else 
      { 
       sql = String.Format("ALTER TABLE {0} ADD COLUMN {1} {2} DEFAULT {3} ", t, f, typ, def); 
      } 
      try 
      { 
       if (openRouteCon()) 
       { 
        OleDbCommand cmd = new OleDbCommand(sql, routedbcon); 
        cmd.ExecuteNonQuery(); 
        string msg = "Modified :" + t + " added col " + f; 
        log.Info(msg); 
        if (def != null) 
        { 
         try 
         { 
          cmd.CommandText = String.Format("update {0} set {1} = {2}", t, f, def); 
          cmd.ExecuteNonQuery(); 
         } 
         catch (Exception e) 
         { 
          log.Error("Could not update column to new default" + t + "-" + f + "-" + e.Message); 
         } 

        } 
        return true; 
       } 
      } 
      catch (Exception ex) 
      { 
       log.Error("Could not alter RouteDB:" + t + " adding col " + f + "-" + ex.Message); 
      } 

     } 
     else 
     { 
      return true; 

     } 
     return false; 
    } 
Cuestiones relacionadas