亚音速在运行时查询信息模式

发布于 2024-12-29 09:23:20 字数 1891 浏览 4 评论 0原文

我在我的 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 调用。

在我的代码中,我正在查询一个表,该表跟踪具有动态列的表: (不确定这是否重要。只是应用程序中对数据库的第一个查询)

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,因为多个数据库具有类似的架构,但有一些自定义表。

I use subsonic 2.2 in my web application. I have a database with many tables.
When the number of foreign keys gets too many the first call to GetSchema hangs for a long time with this query:

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

which I tracked down to the GetTableSchema call in SQLDataProvider.

In my code I am querying a table that keeps track of a table with dynamic columns:
(not sure that it matters. just the first query to the DB in the app)

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]>();

When the query3.Where(...) is called the GetSTableSchema gets called (catching it with SQL Profiler)

My first question is: Why is Subsonic looking at the Schema? It built the schema and the classes and relations when it generated my Data layer?

My second question is: can I make it stop? Is this configurable?

from: With SubSonic is there a way to express relationships without foreign keys?

At runtime SubSonic (at least 2.x) does not rely on any real foreign keys to exist. The information schema is only queried during the DAL generation.

Is this true? Is it possible I have something wrong in my config.

I am using ShareDBConnectionScope due to multiple DBs with Similar schemas but some custom tables.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

三生池水覆流年 2025-01-05 09:23:20

我也有同样的问题。

在第一次调用 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");

I had the same problem.

I placed this code in my app before I call SubSonic the first time.

This will load the schema from the generated code rather than querying the information_schema at runtime

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

}

I also modified the SubSonic Code of MySqlInnoDbDataProvider to avoid InformationSchema Queries during runtime (I prefer an Exception and fix the code)

    /// <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");
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文