microsoft / microsoft/sqlmanagementobjects

JobServer constructor shouldn't run a SQL query

Open
#31 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
C#
Stars
143
Forks
28
PR merge metrics
No merged PRs in 30d

Description

the JobServer class requires initializing its parent's Databases collection to construct itself:

 internal JobServer(Server parentsrv, ObjectKeyBase key, SqlSmoState state) : 
            base(key, state)
        {
            // even though we called with the parent collection of the column, we will 
            // place the JobServer under the right collection
            singletonParent = parentsrv as Server;
            
            // WATCH OUT! we are setting the m_server value here, because JobServer does
            // not live in a collection, but directly under the Database
            SetServerObject( parentsrv.GetServerObject());
            m_comparer = parentsrv.Databases["msdb"].StringComparer;
            jobCategories = null;
            alertCategories = null;
            operatorCategories = null;
            alertSystem = null;
            alerts = null;
            operators = null;
            targetServers = null;
            targetServerGroups = null;
            jobs = null;
            sharedSchedules = null;
        }
  1. It shouldn't be making a SQL query of any kind in the constructor anyway
  2. Populating the databases collection is hugely expensive
  3. SqlSmoObject has a way to delay load StringComparer already that doesn't populate the collection, this object may just need a little refactoring of that method to support specifying msdb as the database to use for the query.

I found this by accident while trying to write a test for something else.
This code blows up because Databases["msdb"] doesn't exist:

var smoFilter = "[contains(@Name, 'SmoBaseline')]";
db.Parent.Databases.ClearAndInitialize($"[@Name='{Urn.EscapeString(db.Name)}']", Enumerable.Empty<string>());
db.Parent.Logins.ClearAndInitialize(smoFilter, Enumerable.Empty<string>());
db.Parent.LinkedServers.ClearAndInitialize(smoFilter, Enumerable.Empty<string>());
if (db.Parent.IsSupportedObject<JobServer>())
{
    db.Parent.JobServer.Jobs.ClearAndInitialize(smoFilter, Enumerable.Empty<string>());
}

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the JobServer constructor shown in the issue and inspect how parentsrv.Databases["msdb"] obtains StringComparer. Compare this with SqlSmoObject's existing delayed StringComparer loading, then use the provided ClearAndInitialize test scenario to verify that constructing JobServer does not populate Databases or fail when msdb is absent.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp, sql
Domain
databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.