Late initialization of ModelTypeClasses (at least) such as PrimaryKeyConstraint.TypeClass??
- Dominant language
- C#
- Stars
- 460
- Forks
- 29
- Avg merge
- 4d 9h
- Merged PRs (30d)
- 7
Description
I'm experimenting with a SSDT DeploymentPlanModifier C# project that, for now, enumerates various constraints being dropped and re-added - this is being loaded by the `SqlPackage.exe` command-line utility with the `/Properties:AdditionalDeploymentContributors= Mine.MyContributor` switch.
I'm able to repeatedly able to demonstrate a frustrating condition of what I guess is a late initialization of some of the DacFX internals. `PrimaryKeyConstraint.TypeClass` is `null`, as is `PrimaryKeyConstraint.Columns`, when the following code is run at full speed:
[ExportDeploymentPlanModifier("Mine.MyContributor", "1.0.0.0")]
public class MyContributor: DeploymentPlanModifier
{
protected override void OnExecute(DeploymentPlanContributorContext context)
{
// PrimaryKeyConstraint
PublishMessage(new ExtensibilityError($"PrimaryKeyConstraints", Severity.Message));
ProcessConstraints(context, PrimaryKeyConstraint.TypeClass, PrimaryKeyConstraint.Columns);
}
}
If I set a breakpoint in Visual Studio before the `ProcessConstraints()` call, the debugger breaks there correctly and the Autos show that both `PrimaryKeyConstraint.TypeClass` and `PrimaryKeyConstraint.Columns` are `null`! Adding an explicit Watch shows the same. Eventually (a minute? though not necessarily time-based), and without allowing the execution to Continue, the Autos eventually change to the non-null, expected values! I'm kind of baffled by this - with the debugger paused, I don't think it's possible for some background thread responsible for populating this value to complete its work - so it must be based on some side-effect of me probing the various values through the IDE. If I wait until after these values are populated to Continue execution, the program runs correctly and gives the expected output. If I don't wait, I can step-into `ProcessConstraints()` with the debugger showing that `null` was passed in - and this gives unexpectedly blank behavior.
I'm not doing any threading or async operations in `ProcessConstraints()` (nor anywhere else). Is there some initialization of the DacFX, or `Ready` event that I must wait for?
Note: I am debugging by having deployed the latest assemblies to `C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\Extensions\Microsoft\SQLDB\DAC\130\Extensions\MyContributor` and running the correlating version of SqlPackage `C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\Extensions\Microsoft\SQLDB\DAC\130\SqlPackage.exe` and not using the Visual Studio Hosting process (not that I know that it's interfering with anything).
The code for `ProcessConstraints()` is uninteresting for this problem, I think. It goes wrong at the very beginning, since typeClass is clearly being passed in as `null`:
private void ProcessConstraints(DeploymentPlanContributorContext context, ModelTypeClass typeClass, ModelRelationshipClass relationshipClass)
{
var droppedPKConstraints =
context.ComparisonResult.ElementsToDrop
.Where(ele => ele.ObjectType == typeClass)
...
Contributor guide
Research direction
Start at the DeploymentPlanModifier.OnExecute entry point and the PrimaryKeyConstraint.TypeClass and PrimaryKeyConstraint.Columns accesses, reproducing through SqlPackage.exe with the AdditionalDeploymentContributors switch. Trace when these values become non-null relative to ProcessConstraints; done means the contributor no longer receives null values during normal execution, or the required initialization/readiness step is identified.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp, sql
- Domain
- database
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100