Skip to content

Fix Database.Owner not reflecting SetOwner() until Refresh() - #231

Open
Andreas Jordan (andreasjordan) wants to merge 2 commits into
microsoft:mainfrom
andreasjordan:fix-database-setowner-stale-owner
Open

Andreas Jordan (andreasjordan) wants to merge 2 commits into
microsoft:mainfrom
andreasjordan:fix-database-setowner-stale-owner

Conversation

@andreasjordan

@andreasjordan Andreas Jordan (andreasjordan) commented Aug 28, 2026 •

Copy link
Copy Markdown

Fixes #40.

SetOwnerImpl only executed the ALTER AUTHORIZATION batch without touching the property bag, so Database.Owner kept returning the previous owner until Refresh() was called.

Rather than writing the caller-provided login name into the property (it may differ from what the server stores, e.g. by casing on a case-insensitive server), the fix invalidates the cached Owner property and marks the property bag lazy - the same pattern CleanObject uses for the default language properties - so the next read of Owner fetches the canonical value from the server. The invalidation is skipped in capture mode since nothing was executed.

The existing Database_CanChangeOwner tests worked around the bug by calling Refresh() before asserting; they now also assert the value before Refresh(). On a case-insensitive server, Database_CanChangeOwner also calls SetOwner with the upper-cased login name and asserts that the server's spelling is returned.

Verified against SQL Server 2019: after SetOwner("sa"), Owner returns sa without Refresh(); after SetOwner with a differently-cased Windows login, Owner returns the server's canonical casing.

This fix was created by Claude and reviewed by Andreas Jordan.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The tests do not verify the server-canonical casing behavior central to the implementation.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)
What changed in this PR

Fixes stale Database.Owner values after SetOwner() by lazily retrieving the canonical server value.

Changes:

  • Invalidates the cached owner after successful execution.
  • Adds immediate-owner functional assertions.
  • Documents the externally visible fix.
File Description
DatabaseBase.cs Invalidates the owner cache.
Database_SmoTestSuite.cs Tests owner access before refresh.
CHANGELOG.md Records the behavior fix.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/FunctionalTest/Smo/ScriptingTests/Database_SmoTestSuite.cs
SetOwnerImpl only executed the ALTER AUTHORIZATION statement without
touching the property bag, so Database.Owner kept returning the previous
owner until Refresh() was called (issue microsoft#40).

Instead of storing the caller-provided login name (which may differ from
the canonical name the server stores, e.g. by casing on a
case-insensitive server), mark the Owner property as not retrieved and
the property bag as lazy - the same pattern CleanObject uses for the
default language properties - so the next read of Owner fetches the
canonical value from the server.

The existing Database_CanChangeOwner tests worked around the bug by
calling Refresh() before asserting; they now also assert the value
before Refresh().

Fixes microsoft#40

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nt casing

The regression assertions only passed the login's stored spelling, so an
implementation that copied the caller-provided name into the property
bag would pass them as well. On a case-insensitive server,
Database_CanChangeOwner now also calls SetOwner with the upper-cased
login name and asserts that Owner returns the name as stored on the
server, without Refresh().

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Microsoft.SqlServer.Management.Smo.Database - .SetOwner() does not change .Owner without .Refresh()

2 participants