问题
I've been researching upgrade procedures for databases, specifically those of the SQLite type.
I'm stuck on how a program knows that, "Hey..this table doesn't exist, lets create it!" or "Hey, it does exist but its three versions behind, lets update it!"
I mean, I could write code specific to every version of every table(Basically that lists what columns should be in it...), then dump it all into a massive if statements for each table or something silly like that, but that would be insane. -`REALLY INSANE.
(I would include that code so you guys could point out how to improve, but I already know that this surely, cannot be the correct way to do it?)
-What technique is actually used to upgrade databases?
I'd like detail specific to:
a)What is the best technique for checking if a table exists or not?
b)How does a program know how many versions behind a table is?
-This is for SQLite 3, being used in a desktop application.
回答1:
A simple approach is to have a special table in your db. Let's assume that this special table is called DBVersion. This table contains only a row with one single numeric column that contain the version number of your database. Initially this table contains the value 0
Now suppose that you have an XML file with a similar schema
<?xml version="1.0" standalone="yes"?>
<DatabaseUpdater>
<xs:schema id="DatabaseUpdater" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="DatabaseUpdater" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="UpdateCMD">
<xs:complexType>
<xs:sequence>
<xs:element name="DBType" type="xs:int" minOccurs="0" />
<xs:element name="Version" type="xs:int" minOccurs="0" />
<xs:element name="Command" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
<UpdateCMD>
<DBType>1</DBType>
<Version>1</Version>
<Command>CREATE TABLE userTable ......
</Command>
</UpdateCMD>
</DatabaseUpdater>
Now you could write code that read the database DBVersion table number and then load the XML file, search for commands with a Version value higher than the version number in the DBVersion table and execute them. After successful execution, update the Version number in the DBVersion table. (Special care should be taken here to avoid errors and a log file should be imperative).
int currentVersion = GetDBVersionNumber();
string scriptFile = "UPGRADE_DB.XML";
DataSet ds = new DataSet();
ds.ReadXml(scriptFile, XmlReadMode.ReadSchema);
string filter = "Version > " + currentVersion.ToString();
string sort = "Version";
DataRow[] rows = ds.Tables[0].Select(filter, sort);
if (rows.Length == 0)
return;
try
{
using(SQLiteConnection cnn = new SQLiteConnection(.....))
using(SQLiteCommand cmd = cnn.GetCommand())
{
foreach (DataRow dr in rows)
{
cmd.CommandText = dr.Field<string>("Command");
cmd.CommandType = CommandType.Text;
cmd.ExecuteNonQuery();
UpdateDBVersionNumber(dr.Field<int>("Version"));
WriteLog(currentVersion);
}
}
}
catch(Exception ex)
{
WriteLog(ex);
}
When you need to upgrade your database you simply add another 'record' to the XML file and distribute it to your customers. The application should be able to upgrade the database without any change in your code for this specific purpose
回答2:
The most widely used way is that used by Android: this is handled with the SQLiteOpenHelper class, which stores a version number in the database (using PRAGMA user_version, but the exact mechanism does not matter) and has onCreate
/onUpdate
callbacks for the app to handle these cases.
You don't need to check individual tables; the database version number takes care of that. (You can keep everything consistent by putting the entire update into a transaction.)
Look at the source (especially getDatabaseLocked
) and implement something similar.
When you have multiple older versions, a typical way to handle this is as follows:
if (oldVersion < 2)
{
// update everything from version 1 to 2
}
if (oldVersion < 3)
{
// update everything from version 2 to 3
}
...
来源:https://stackoverflow.com/questions/25089540/upgrading-winforms-sqlite-database-techniques