dataobjects-net icon indicating copy to clipboard operation
dataobjects-net copied to clipboard

Custom (ignored) columns in customized (ignored) indexes causes an ArgumentException when extracting the schema

Open ondrejtucny opened this issue 10 months ago • 0 comments

I've run into a situation that looks like a bug in the schema extractor with respect to IgnoreRules, related to changes introduced for the sake of #192 . I am using version 7.1.4 under .NET 6.

SQL schema extraction causes an unhandled ArgumentException:

<Exception>
    <ExceptionType>System.ArgumentException, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e</ExceptionType>
    <Message>Item with name 'ext_PartitionGroup' already exists.</Message>
    <Source>Xtensive.Orm</Source>
    <HelpLink />
    <Data>
        <HandlingInstanceId>cc451358-8c16-4d2d-8d3c-57cf46322119</HandlingInstanceId>
    </Data>
    <AdditionalInfo>
        <MachineName>CSOB-UC11</MachineName>
        <TimeStamp>2025-03-12 04:21:11.650+01:00</TimeStamp>
        <FullName>Bee.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null</FullName>
        <AppDomainName>DieboldNixdorf.UniCard.Console</AppDomainName>
        <ThreadIdentity>unknown</ThreadIdentity>
    </AdditionalInfo>
    <StackTrace>   at Xtensive.Sql.Model.NodeCollection`1.Add(TNode item)
   at Xtensive.Sql.Model.PairedNodeCollection`2.Add(TNode item)
   at Xtensive.Sql.Model.IndexColumn.set_Index(Index value)
   at Xtensive.Sql.Model.IndexColumn..ctor(Index index, DataTableColumn column, Boolean ascending)
   at Xtensive.Sql.Model.Index.CreateIndexColumn(DataTableColumn column, Boolean ascending)
   at Xtensive.Sql.Drivers.SqlServer.v09.Extractor.ReadIndexColumnData(DbDataReader reader, ExtractionContext context, Int32&amp; tableId, Int32 spatialIndexType, PrimaryKey&amp; primaryKey, UniqueConstraint&amp; uniqueConstraint, Index&amp; index, ColumnResolver&amp; table)
   at Xtensive.Sql.Drivers.SqlServer.v09.Extractor.ExtractIndexes(ExtractionContext context)
   at Xtensive.Sql.Drivers.SqlServer.v09.Extractor.ExtractCatalogContents(ExtractionContext context)
   at Xtensive.Sql.Drivers.SqlServer.v11.Extractor.ExtractCatalogContents(ExtractionContext context)
   at Xtensive.Sql.Drivers.SqlServer.v09.Extractor.ExtractSchemes(String catalogName, String[] schemaNames)
   at Xtensive.Sql.SqlDriver.Extract(SqlConnection connection, IEnumerable`1 tasks)
   at Xtensive.Orm.Providers.StorageDriver.Extract(SqlConnection connection, IEnumerable`1 tasks)
   at Xtensive.Orm.Providers.SqlExecutor.Extract(IEnumerable`1 tasks)
   at Xtensive.Orm.Upgrade.SqlWorker.ExtractSchema(UpgradeServiceAccessor services, ISqlExecutor executor)
   at Xtensive.Orm.Upgrade.SqlWorker.Run(UpgradeServiceAccessor services, SqlWorkerTask task)
   at Xtensive.Orm.Upgrade.SqlWorker.&lt;&gt;c__DisplayClass0_0.&lt;Create&gt;b__0()
   at System.Threading.Tasks.Task`1.InnerInvoke()
   at System.Threading.Tasks.Task.&lt;&gt;c.&lt;.cctor&gt;b__272_0(Object obj)
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task&amp; currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location ---
   at Xtensive.Core.AsyncFutureResult`1.Get()
   at Xtensive.Orm.Upgrade.UpgradingDomainBuilder.CompleteSqlWorker()
   at Xtensive.Orm.Upgrade.UpgradingDomainBuilder.BuildMultistageDomain()
   at Xtensive.Orm.Upgrade.UpgradingDomainBuilder.Run()
   at Xtensive.Orm.Upgrade.UpgradingDomainBuilder.Build(DomainConfiguration configuration)
   at Xtensive.Orm.Domain.Build(DomainConfiguration configuration)
   at Holygrail.Platform.Data.Model.Database.DomainController.GetDomainInternal(String csName, IDomainModelProvider domainModel, DomainUpgradeMode upgradeMode)</StackTrace>
</Exception>

My goal is to setup partitioning for the tables which are subject to complicated state management and queuing logic. Partitioning is a necessary performance optimization. In my schema, I have the ext_PartitionGroup calculated column, which determines the destination partition. For this to work, the column must be part of the primary key. It's done like this:

ALTER TABLE CardSec.CardServiceLevelSetting ADD CONSTRAINT
	PK_CardServiceLevelSetting PRIMARY KEY CLUSTERED (Id, ext_PartitionGroup) ON PS_CardSecClassification(ext_PartitionGroup)
GO

I have ignore rules defined in the domain configuration like this:

// define ignore rules for manually introduced customizations (case-insensitive)
cfg.IgnoreRules.IgnoreTable("ext_*"); // manually-introduced extension tables
cfg.IgnoreRules.IgnoreIndex("ext_*");  // manually-introduced extension indexes
cfg.IgnoreRules.IgnoreColumn("ext_*"); // manually-introduced extension columns

I did try renaming the primary key to ext_PK_CardServiceLevelSetting, but the extraction fails, too.

Unfortunately, right now I have not much additional information I could share, nor a minimal reproducible example. The scripts setting up partitioning are quite large and do other things as well, such as setting several other indexes (all are ext_). I will be using a Debug build of DataObjects and try to inspect this in the debugger, and post what I discover.

ondrejtucny avatar Mar 12 '25 15:03 ondrejtucny