Дозвуковые запросы информационной схемы во время выполнения - PullRequest
1 голос
/ 27 января 2012

Я использую Subson 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

, который я отследил до вызова GetTableSchema в SQLDataProvider.

В моем коде я запрашиваю таблицу, которая отслеживает таблицу с динамическими столбцами: (не уверен, что это имеет значение. просто первый запрос к БД в приложении)

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 Profiler)

Мой первый вопрос: почему Subsonic смотрит на схему? Он создал схему, классы и отношения, когда сгенерировал мой Уровень данных?

Мой второй вопрос: могу ли я остановить это? Это настраивается?

от: С SubSonic есть ли способ выразить отношения без внешних ключей?

Во время выполнения SubSonic (как минимум 2.x) не полагается на существование каких-либо реальных внешних ключей. Информационная схема запрашивается только во время генерации DAL.

Это правда? Возможно ли, что у меня что-то не так в моей конфигурации.

Я использую ShareDBConnectionScope из-за нескольких БД с похожими схемами, но с некоторыми пользовательскими таблицами.

1 Ответ

0 голосов
/ 10 февраля 2012

У меня была такая же проблема.

Я поместил этот код в свое приложение перед первым вызовом SubSonic.

Это будет загружать схему из сгенерированного кода, а не запрашивать информационную_схему во время выполнения

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

}

Я также изменил код SubSonic MySqlInnoDbDataProvider, чтобы избежать запросов 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");
...