1

Web アプリケーションで subsonic 2.2 を使用しています。多くのテーブルを持つデータベースがあります。外部キーの数が多すぎると、GetSchema への最初の呼び出しが次のクエリで長時間ハングします。

SELECT
    FK_Table  = FK.TABLE_NAME,
    FK_Column = CU.COLUMN_NAME,
    PK_Table  = PK.TABLE_NAME,
    PK_Column = PT.COLUMN_NAME, 
    Constraint_Name = C.CONSTRAINT_NAME,
    Owner = FK.TABLE_SCHEMA
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS C
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS FK ON C.CONSTRAINT_NAME = FK.CONSTRAINT_NAME
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS PK ON C.UNIQUE_CONSTRAINT_NAME = PK.CONSTRAINT_NAME
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CU ON C.CONSTRAINT_NAME = CU.CONSTRAINT_NAME
INNER JOIN
    (   
        SELECT i1.TABLE_NAME, i2.COLUMN_NAME
        FROM  INFORMATION_SCHEMA.TABLE_CONSTRAINTS i1
        INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE i2 ON i1.CONSTRAINT_NAME = i2.CONSTRAINT_NAME
        WHERE i1.CONSTRAINT_TYPE = 'PRIMARY KEY'
    ) 
PT ON PT.TABLE_NAME = PK.TABLE_NAME

SQLDataProvider の GetTableSchema 呼び出しまで追跡しました。

私のコードでは、動的列を持つテーブルを追跡するテーブルにクエリを実行しています:(それが重要かどうかはわかりません。アプリのDBへの最初のクエリのみ)

SubSonic.Select select3 = new SubSonic.Select();
SubSonic.SqlQuery 
query3.Where("[MY_TABLE_NAME_IS_PRIVATE]").IsEqualTo("[MY_TABLE_NAME_IS_PRIVATE]");
List<[MY_TABLE_NAME_IS_PRIVATE]> subSonicList3 = query3.ExecuteTypedList<[MY_TABLE_NAME_IS_PRIVATE]>();

query3.Where(...)が呼び出されると、がGetSTableSchema呼び出されます (SQL プロファイラーでキャッチします)。

私の最初の質問は、Subsonic がスキーマを見ているのはなぜですか? 私のデータ層を生成したときに、スキーマとクラスと関係を構築しましたか?

私の2番目の質問は、それを止めることができますか? これは構成可能ですか?

from: SubSonic では、外部キーなしで関係を表現する方法はありますか?

実行時に SubSonic (少なくとも 2.x) は、実際の外部キーの存在に依存しません。情報スキーマは、DAL の生成中にのみ照会されます。

これは本当ですか?私の設定に何か問題がある可能性はありますか?

類似のスキーマを持つ複数の DB がいくつかのカスタム テーブルがあるため、ShareDBConnectionScope を使用しています。

4

1 に答える 1

0

私も同じ問題を抱えていました。

SubSonic を初めて呼び出す前に、このコードをアプリに配置しました。

これにより、実行時に information_schema をクエリするのではなく、生成されたコードからスキーマが読み込まれます。

foreach (var type in this.GetType().Assembly.GetExportedTypes())
{

    if (type.BaseType != null && type.BaseType.IsGenericType && type.BaseType.FullName != null && type.BaseType.FullName.StartsWith("SubSonic.ActiveRecord`1"))
    {
        type.GetMethod("GetTableSchema", BindingFlags.NonPublic | BindingFlags.Static).Invoke(null, null);
    }

}

また、MySqlInnoDbDataProvider の SubSonic コードを変更して、実行時の InformationSchema クエリを回避しました (例外を優先し、コードを修正しました)。

    /// <summary>
    /// Gets the table schema.
    /// </summary>
    /// <param name="tableName">Name of the table.</param>
    /// <param name="tableType">Type of the table.</param>
    /// <returns></returns>
    public override TableSchema.Table GetTableSchema(string tableName, TableType tableType)
    {

        if (schemaCollection.ContainsKey(tableName))
            return schemaCollection[tableName];

        // Avoid querying the information_schema @ runtime
        if (DataService.Provider.Name == "MyProviderName")
            throw new InvalidOperationException("Querying Information_Schema at runtime is not a good idea. The caller should use DataService.GetTableSchema(tableName, providerName) instead of DataService.Provider.GetTableSchema(providerName) to force the use of the cached TableSchema definition");
于 2012-02-10T10:03:43.473 に答える