fix(data): model convert silently drops relationships and picklist columns - #190
Draft
david-hudec-networg wants to merge 2 commits into
Draft
Conversation
…convert Two defects in DataModelConverter, both silent — the output stays well-formed while losing model content, so nothing surfaces until you diff against source. 1. Relationship dedup keyed on (LeftSideTable, RightSideTable), ignoring the column. Every N:1 relationship after the first between the same table pair was discarded. talxis_project has four separate lookups to account (building authority, city, city district, architectural studio); only one got an edge, while all four columns still rendered — so the diagram understated the model without looking broken. Fixed by including LeftSideRow in the key, which is also what dbdiagram actually constrains (the endpoint pair, not the table pair), so genuine duplicates still collapse. 2. Picklist/state/status/bit rows whose OptionSetName could not be resolved were deleted outright. Three triggers seen in the wild: an option set declared with <options />, an option set owned by a different module, and platform-owned sets (activitypointer_*). Required, form-visible business columns disappeared, and a module whose only contribution was such an attribute looked like a non-contributor. Now the row is downgraded to Int instead of removed. OptionSetName is cleared too, because ToDbDiagramNotation prefers it over RowType and the column would otherwise reference an Enum never emitted. Measured on two unrelated solutions: Project Model layer refs 9 -> 14 (the 5 lost account lookups return) Service/Project/Model refs 87 -> 99, columns 911 -> 918 table and Enum counts unchanged; no duplicate endpoint pairs introduced; no column left typed as an undeclared Enum. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Clearing OptionSetName is sufficient and is all the DBML problem requires — it is what ToDbDiagramNotation prefers over RowType. Also forcing RowType.Int reached past DBML into every other target sharing ParseModules, overriding each translator's own handling of the kind: target column Int version this version sql activitytypecode int nvarchar(255) dbml activitytypecode Int Picklist edmx isregularactivity Edm.Boolean Edm.Boolean (unchanged) nvarchar(255) is SQLTranslator's own existing fallback for a picklist it cannot resolve, so leaving RowType alone keeps the tool self-consistent instead of imposing a DBML-driven choice on sql and edmx. One line instead of two. Verified on three declaration folders, all three targets, no dangling enum references in the DBML output. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two defects in
DataModelConverter. Both are silent: output stays well-formed while losing model content, so nothing surfaces until you diff against the source declarations. Found while building a layered ERD across a product base and three customer solutions.1. N:1 relationships deduped on the table pair, not the column
DataModelConverterService.cs:492compares onlyLeftSideTableandRighSideTable, so every relationship after the first between the same pair is dropped.talxis_projecthas four separate lookups toaccount— building authority, city, city district, architectural studio. One edge was emitted. All four columns still rendered, because columns are emitted separately from relationships, so the diagram understated the model without looking broken.Fix: include
LeftSideRowin the key.Table.GetOrCreateRowcaches by name, so two relationships through the same column share oneTableRowinstance and reference equality holds. That is also what dbdiagram constrains — the endpoint pair, not the table pair — so genuinely duplicated declarations still collapse, which is presumably why the guard exists.2. A picklist column is deleted when its option set will not resolve
The filter at
:366removesPicklist/Multiselectoptionset/State/Status/Bitrows whoseOptionSetNameis not among the resolved option sets. Three triggers observed:<options />activitypointer_*,socialprofile_*) with no file in the repoRequired, form-visible business columns disappear with no warning, and a module whose only contribution is such an attribute reads as a non-contributor.
Fix: clear
OptionSetNameinstead of deleting the row. That is the minimum the problem needs —ToDbDiagramNotationprefersOptionSetNameoverRowType, so a stale name would reference anEnumthat was never emitted.RowTypeis deliberately left alone so each translator keeps its own handling:sqlfalls back to its existingnvarchar(255)for an unresolvable picklist,edmxkeepsEdm.Booleanfor a bit, anddbmlrenders the bare kind. An earlier revision of this PR also forcedRowType.Int; that reached past DBML into every target sharingParseModulesand imposed a DBML-driven choice onsqlandedmx, so it was reverted.Measured
Built from source, baseline vs patched, on three real declaration folders:
ModellayerService/Project/ModelEnvironment/Bootstrap/ModelTable and
Enumcounts unchanged in all three. No duplicate endpoint pairs introduced. No column left typed as an undeclaredEnum. All three targets (dbml,sql,edmx) exercised.Notes
:439-455) is untouched and correct for the non-self-referential case. A separate defect exists there — a self-referencing N:N emits the intersect column twice and theRef:line twice — which this PR does not address.DataModelConvertTests.csis entirely[Fact(Skip = ...)]integration tests needing a real solution on disk.ParseModulesispublic staticand both defects are unit-testable from in-memoryXDocumentfixtures; happy to add them wherever you would want them, but I did not want to guess at placement in a draft.ModuleseedsColorhexfromnew Random(), so the same unchanged solution converts to a different file every time), and the synthesised<entity>idprimary key is wrong for activity entities — the latter is not fixable here, since the only layer that triggers key synthesis is also the layer that omitsIsActivity.🤖 Generated with Claude Code