Ir al contenido


Foto

Recomendaciones para actualizar el esquema de la base de datos


  • Por favor identifícate para responder
6 respuestas en este tema

#1 axesys

axesys

    Advanced Member

  • Moderadores
  • PipPipPip
  • 640 mensajes
  • LocationLos Mochis

Escrito 02 abril 2018 - 05:21

Hola a todos, alguien se a topado con este tipo de situación, que se necesita actualizar el esquema de la base de datos que esta en producción de forma automática cada vez que se libera una nueva versión del programa, siempre y cuando halla habido cambios en la base de datos de desarrollo.

 

Saludos


  • 0

#2 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 03 abril 2018 - 11:00

En mi caso no, pero para esos fines existen los ORM como MorMot que hacen el trabajo sucio, y como estoy en un proyecto C#  y Entity Framework (Por obligación) y en PHP con Laravel y cakePHP, esos ya vienen con eso resuelto, en Delphi hace falta ese tipo de programación, creo repuntaría mucho más..


  • 0

#3 axesys

axesys

    Advanced Member

  • Moderadores
  • PipPipPip
  • 640 mensajes
  • LocationLos Mochis

Escrito 03 abril 2018 - 11:13

Por el momento encontré esta solución almacenar un número de versión en la base de datos y un número de versión en la aplicación. Cada vez que se necesite cambiar la estructura de la base de datos, crear un código para actualizar la estructura de la base de datos y aumentar el número de versión en la aplicación. Cuando se inicia la aplicación, comparar números y si es necesario, ejecutar algún código para actualizar la estructura de la base de datos y actualizar el número de versión de la base de datos. Por lo tanto, la base de datos está actualizada con la aplicación. El código es algo así


delphi
  1. if DBVersion < AppVersion then
  2. begin
  3. for i := DBVersion+1 to AppVersion do
  4. UpdateStructure(i);
  5. end
  6. else
  7. if DBVersion > AppVersion then
  8. raise EWrongVersion.Create('Wrong application for this database');

UpdateStructure simplemente ejecuta el código necesario, algo así como:


delphi
  1. procedure UpdateStructure(const aVersion : Integer);
  2. begin
  3. case aVersion of
  4. 1 : //some db code
  5. 2 : //some more db code
  6. ...
  7. ...
  8. end;
  9. UpdateDatabaseVersion(aVersion);
  10. end;

Se puede usar el mismo código para crear la base de datos desde cero:


delphi
  1. CreateDatabase;
  2. for i := 1 to AppVersion do
  3. UpdateStructure(i);

Saludos


  • 1

#4 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 03 abril 2018 - 07:29

La verdad que lo que comenta Fernando es lo adecuado.. en frameworks como Rails o Laravel existe el concepto de "migraciones". Las migraciones de las BD son basicamente clases especiales que permiten a uno definir las sentencias de creacion y actualizacion de estructura de las tablas. El framework despues se encarga de versionarlas, es decir, sabe cual hay que aplicar o cual hay que quitar para pasar de una version a otra. Como si fuera git pero para la base

 

En java incluso se le puede decir que solito cree la estructura de las tablas. 

 

Ciertamente algo asi para Delphi seria "la hostia"

 

Spring tiene un ORM que fue integrado hace poco, Marshmallow. Nunca he investigado para ver si ofrece alguna solucion. El simple hecho de poder escribir SQL agnostico contra cualquier tipo de base ya seria un avance enorme para poder implementar esto. Piensen en lo mas sencillo: como se define una clave primaria autoincremental en SQLServer? Y en firebird? Y en postgre? Y en Mysql? En todos es disitnto


  • 0

#5 axesys

axesys

    Advanced Member

  • Moderadores
  • PipPipPip
  • 640 mensajes
  • LocationLos Mochis

Escrito 04 abril 2018 - 03:31

Por lo visto hay varios Frameworks para eso

 

http://instantobjects.sourceforge.net/

 

http://tiopf.sourceforge.net

 

https://code.google.com/p/delphi-orm/

 

https://sourceforge....arryhengensopf/

 

http://www.macrobjec...bject/index.htm

 

https://www.tmssoftw...te/aurelius.asp

 

De momento con este código lo tengo resuelto


delphi
  1. uses Windows;
  2.  
  3. function GetAppVersion: word;
  4. var
  5. VerInfoSize, VerValueSize, Dummy: DWORD;
  6. VerInfo: Pointer;
  7. VerValue: PVSFixedFileInfo;
  8. begin
  9. Result:= 0;
  10. VerInfoSize := GetFileVersionInfoSize(PChar(ParamStr(0)), Dummy);
  11. if VerInfoSize > 0 then
  12. begin
  13. GetMem(VerInfo, VerInfoSize);
  14. try
  15. if GetFileVersionInfo(PChar(ParamStr(0)), 0, VerInfoSize, VerInfo) then
  16. begin
  17. VerQueryValue(VerInfo, '\', Pointer(VerValue), VerValueSize);
  18. with VerValue^ do
  19. begin
  20. Result := dwFileVersionMS shr 16;
  21. // V2 := dwFileVersionMS and $FFFF;
  22. // V3 := dwFileVersionLS shr 16;
  23. // V4 := dwFileVersionLS and $FFFF;
  24. end;
  25. end;
  26. finally
  27. FreeMem(VerInfo, VerInfoSize);
  28. end;
  29. end;
  30. end;
  31.  
  32. function TdmGlobal.TableExist: boolean;
  33. var
  34. oList: TStrings;
  35. begin
  36. oList := TStringList.Create;
  37. try
  38. cntData.GetTableNames('', '', 'AJUSTE', oList);
  39. Result := oList.Count > 0;
  40. finally
  41. oList.Free;
  42. end;
  43. end;
  44.  
  45. function TdmGlobal.GetDBVersion: integer;
  46. begin
  47. if TableExist then
  48. with qryData do
  49. begin
  50. Close;
  51. SQL.Clear;
  52. SQL.Add('SELECT valor FROM ajuste WHERE nombre = ' + QuotedStr('VERSION'));
  53. Open;
  54. Exit(FieldByName('valor').AsInteger);
  55. end
  56. else
  57. Result := 0
  58. end;
  59.  
  60. procedure TdmGlobal.InitData(cntName: string);
  61. var
  62. AppVersion: integer;
  63. DBVersion: integer;
  64. i: integer;
  65. begin
  66. cntData.Close;
  67. cntData.Params.Database:= 'C:\AppData\' + cntName + '.fdb';
  68. cntData.Open;
  69. DBVersion:= GetDBVersion;
  70. AppVersion:= GetAppVersion;
  71. if AppVersion > DBVersion then
  72. begin
  73. Script.SQLScripts.Clear;
  74. Script.SQLScripts.Add;
  75. for i := DBVersion to Pred(AppVersion) do
  76. UpdateStructure(i + 1);
  77. Script.ValidateAll;
  78. Script.ExecuteAll;
  79. UpdateDatabaseVersion(i);
  80. end;
  81. end;
  82.  
  83. procedure TdmGlobal.UpdateDatabaseVersion(aVersion: integer);
  84. begin
  85. with qryData do
  86. begin
  87. Close;
  88. SQL.Clear;
  89. SQL.Add('update ajuste set valor = ' + IntToStr(aVersion));
  90. SQL.Add('where nombre = ' + QuotedStr('VERSION'));
  91. ExecSQL;
  92. end;
  93. end;
  94.  
  95. procedure TdmGlobal.UpdateStructure(aVersion: integer);
  96. begin
  97. with Script.SQLScripts.Add do
  98. begin
  99. Name:= 'S' + IntToStr(aVersion);
  100. SQL.LoadFromStream(
  101. TResourceStream.Create(hInstance, Name, RT_RCDATA));
  102. Script.SQLScripts[0].SQL.Add('@' + Name);
  103. end;
  104. end; 

Uso un conector de Firedac, un FDQuery y un FDScript, en el FDScript le agregue un FDSQLScript para después en su posición 0 agregar los nombres de los scripts que se van a llamar, estos scripts son archivos de texto que agregue en el proyecto como recursos, los quise llamar directamente sin usar sus nombres pero no me funciono.

 

Saludos


  • 3

#6 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 05 abril 2018 - 10:36

Parece que esto soluciona este problema, de manera independiente del lenguaje; aunque solo puedo decir que me han comentado que funciona muy bien, pero no he investigado nada sobre el tema

 

Liquibase


  • 0

#7 axesys

axesys

    Advanced Member

  • Moderadores
  • PipPipPip
  • 640 mensajes
  • LocationLos Mochis

Escrito 06 abril 2018 - 11:45

Parece que esto soluciona este problema, de manera independiente del lenguaje; aunque solo puedo decir que me han comentado que funciona muy bien, pero no he investigado nada sobre el tema

 

Liquibase

Se ve interesante, tal vez más adelante cuando se complique más la base de datos valdría la pena usarlo, por lo pronto estoy usando el programa Database Comparer para generar los scripts.

 

Saludos


  • 0




IP.Board spam blocked by CleanTalk.