我的应用实际上使用SqlServerCe
(Microsoft SqlServer Compact)。现在,通过我的新更新,我换到了SQLite
。
现在我的问题:每次用户想要导入数据库时,他都可以导入SqlServerCe
文件(旧备份)或SQLite
(新备份)。如何检测DbProviderFactory
需要DbConnection
哪个?
/// <summary>
/// Verifies the db if it is not corrupt! If the return value is <see cref="Nullable"/>, the DB is corrupt!
/// </summary>
/// <returns><see cref="Array"/> of <see cref="int"/>. The 1. index is Components.Count(), the 2 index is the Recipes.Count()!!</returns>
[CanBeNull]
public static int[] ImportDB_Verify()
{
try
{
SqlCeProviderFactory provider = new SqlCeProviderFactory();
SqlCeConnectionStringBuilder connectionStringBuilder = new SqlCeConnectionStringBuilder
{
DataSource = "Path/to/foo.db"
};
int[] val = new int[2];
using (DbConnection dbConnection = provider.CreateConnection())
{
dbConnection.ConnectionString = connectionStringBuilder.ConnectionString;
dbConnection.Open();
using (DbCommand dbCommand = dbConnection.CreateCommand("SELECT Count(*) FROM Components"))
{
val[0] = (int)dbCommand.ExecuteScalar();
}
using (DbCommand dbCommand = dbConnection.CreateCommand("SELECT Count(*) FROM Recipes"))
{
val[1] = (int)dbCommand.ExecuteScalar();
}
}
return val;
}
catch (Exception ex)
{
_Logger.Error(ex);
return null;
}
}
如果有更好的东西,请告诉我!
/// <summary>
/// Verifies the db if it is not corrupt! If the return value is <see cref="Nullable"/>, the DB is corrupt!
/// </summary>
/// <returns><see cref="Array"/> of <see cref="int"/>. The 1. index is components.Count(), the 2 index is the recipes.Count()!!</returns>
[CanBeNull]
public static int[] ImportDB_Verify()
{
int[] val = new int[2];
Exception sqLiteException;
try
{
SQLiteFactory provider = new SQLiteFactory();
SQLiteConnectionStringBuilder connectionStringBuilder = new SQLiteConnectionStringBuilder
{
DataSource = Core.CommonAppDataPath + "tmp.HTdb"
};
using (DbConnection dbConnection = provider.CreateConnection())
{
dbConnection.ConnectionString = connectionStringBuilder.ConnectionString;
dbConnection.Open();
using (DbCommand dbCommand = dbConnection.CreateCommand("SELECT Count(*) FROM components;"))
{
val[0] = (int)dbCommand.ExecuteScalar();
}
using (DbCommand dbCommand = dbConnection.CreateCommand("SELECT Count(*) FROM recipes;"))
{
val[1] = (int)dbCommand.ExecuteScalar();
}
}
return val;
}
catch (Exception ex)
{
sqLiteException = ex;
}
try
{
SqlCeProviderFactory provider = new SqlCeProviderFactory();
SqlCeConnectionStringBuilder connectionStringBuilder = new SqlCeConnectionStringBuilder
{
DataSource = Core.CommonAppDataPath + "tmp.HTdb"
};
using (DbConnection dbConnection = provider.CreateConnection())
{
dbConnection.ConnectionString = connectionStringBuilder.ConnectionString;
dbConnection.Open();
using (DbCommand dbCommand = dbConnection.CreateCommand("SELECT Count(*) FROM Components;"))
{
val[0] = (int)dbCommand.ExecuteScalar();
}
using (DbCommand dbCommand = dbConnection.CreateCommand("SELECT Count(*) FROM Recipes;"))
{
val[1] = (int)dbCommand.ExecuteScalar();
}
}
return val;
}
catch (Exception ex)
{
_Logger.Error(ex, $"Error while verifying the database. The SQLite Exception: {sqLiteException}");
return null;
}
}
答案 0 :(得分:2)
打开文件并阅读其#34;幻数&#34;。 SQLite数据库以ASCII字符串&#34; SQLite格式&#34;开头,SQL Server CE 0x01 0x0F 0x00 0x00
文件以.MDF
开头,就我所见,即它们看起来像{{1}文件。
这样的事情:
byte[] buffer = new byte[4];
using (var fileStream = File.OpenRead(databasefile))
{
fileStream.Read(buffer, 0, 4);
}
if (buffer[0] == 83 // S
&& buffer[1] == 81 // Q
&& buffer[2] == 76 // L
&& buffer[3] == 105) // i
{
// SQLite
}
else
{
// Assume SQL Server CE
}
请注意,用户仍然可以为您的代码提供一个恰好以&#34; SQLi&#34;开头的文本文件。但不是一个SQLite文件,所以你不能也不应该使用这种方法删除你的异常处理代码。
答案 1 :(得分:1)
使用@ CodeCaster的答案:
public enum DBType { SQLite, SQLServerCe };
public static DBType GetDatabaseType(string filename)
{
byte[] buffer = new byte[4];
using (var fileStream = File.OpenRead(databasefile))
{
fileStream.Read(buffer, 0, 4);
}
if (buffer[0] == 83 // S
&& buffer[1] == 81 // Q
&& buffer[2] == 76 // L
&& buffer[3] == 105) // i
{
return DBType.SQLite;
}
else
{
return DBType.SQLServerCe;
}
}
public static int[] ImportDB_Verify()
{
string dbFilePath = "someDatabaseFile"
DBType detectedType = GetDatabaseType(dbFilePath);
if(detectedType == DBType.SQLite)
return VerifySQLiteDb(dbFilePath);
else
return VerifySQLServerCeDb(dbFilePath);
}
private static int[] VerifySQLiteDb(string dbFilePath)
{
//...
// exception handling etc.
}
private static int[] VerifySQLServerCeDb(string dbFilePath)
{
//...
// exception handling etc.
}