C#检测数据库格式| DbProviderFactory

时间:2016-11-03 12:17:59

标签: c# sql sqlite

我的应用实际上使用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;
        }
    }

尝试Catch&#34;解决方案&#34;

如果有更好的东西,请告诉我!

    /// <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;
        }
    }

2 个答案:

答案 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.
}
相关问题