Visual Studio Community 2017 – Upgrading

Background

The lead developer on one of our projects experienced problems deploying a report yesterday evening.

It is time to see if we can duplicate and thus research the error.

 

SQL Server Data Tools

SQL Server Data Tools – v2015

Downloaded SQL Server Data Tools (SSDT) v2015 from here.

Was able to successfully install and deploy the report.

 

SQL Server Data Tools – v2017

Download

From same link, downloaded SSDT v2017.

Install

Prerequisite

Visual Studio 2017

Blocking Issue
Textual

The current installation requires Visual Studio 2017 version number 15.3.0 or higher.  Please upgrade your Visual Studio instance before continuing the setup.

Image

 

Validate v2017

Launched our installed v2017 and validated the Version # is 15.2 (26430.15 )

Image

Textual

Microsoft Visual Studio Community 2017
Version 15.2 (26430.15) Release
VisualStudio.15.Release/15.2.0+26430.15
Microsoft .NET Framework
Version 4.7.02053

Review Visual Studio 2017 Packages

Let us quickly review Visual Studio ( VS) 2017 Release History

Image

Explanation
  1. v15.2
    • We have v15.2, released on May 10th, 2017
  2. v15.3
    • We need at least 15.3, released on August 14th, 2017
  3. v15.4.3
    • The latest as of today, 2017-Nov-9th, is v15.4.3
Download Visual Studio 2017 – Bootstrapper

We will to “Install Visual Studio 2017 on low bandwidth or unreliable network environments” ( here  )and reach for the Bootstrapper community edition.

The direct link to Community edition is here.

 

Create an offline installer

Let us create an offline installer


set "_target=C:\VS2017offline"
set "_desktop=Microsoft.VisualStudio.Workload.ManagedDesktop"
set "_netWeb=Microsoft.VisualStudio.Workload.NetWeb"
set "_github=Component.GitHub.VisualStudio"

vs_community.exe --layout %_target% --add %_desktop% --add %_netWeb%  --add %_github% --includeOptional --lang en-US

 

Build offline installer

Run the batch file created earlier to build the offline installer.

Image – Invoke batch file

Image – download…

Image – Successful
Patch Visual Studio 2017

Let us patch our installed v2017

Run the setup.exe availed through the offline installer.

Image – 1

Update available

Visual Studio 2017 is already installed.

Click update to update to version 15.4.3

 

Image – 2

Image – 3

 

Image – 4

 

Image – 5

 

Validate Visual Studio 2017 Version

Launch Visual and validated that v2017 is installed.

 

Install

Steps

Let us go back and try to install SQL Server Data Tools – Release 15.4.0 Preview

Install Tools to this Visual Studio 2017 instance

 

References

  1. Microsoft
    • Docs / SQL / SSDT ( SQL Server Data Tools )
      • Download SQL Server Data Tools ( SSDT )
        Link
    • Docs / Visual Studio / Documentation / Installation
      • Install Visual Studio 2017 on low bandwidth or unreliable network environments
        Link
      • Create an offline installation of Visual Studio 2017
        Link
    • VisualStudio.com
      • Visual Studio 2017 version 15.4 Release Notes
        Link

SQL Server – v2005 – Report Creation Tools

Background

I am trying to create Custom Reports to be ran against a SQL Server v2005 Instance.

Unfortunately, having problems accessing my Business Intelligence Development (BIDS) .

Here is what the Start Screen looks like:

startup-v2005

 

Add BIDS To Existing Installation

Tried numerous times to augment my v2005 installation with BIDs.

GUI

yourupgradeisblocked

Textual

Name: Microsoft SQL Server 2005 Tools (64-bit)
Reason: Your upgrade is blocked. For more information about upgrade support, see the “Version and Edition Upgrades” and “Hardware and Software Requirements” topics in SQL Server 2005 Setup Help or SQL Server 2005 Books Online.

Build version check:
Your upgrade is blocked because the existing component is a later version than the version you are trying to upgrade to. To modify an existing SQL Server component, go to Add or Remove Programs in Control Panel, select the component you would like to modify, and then click Change/Remove.

Edition check:
Your upgrade is blocked because of edition upgrade rules. For more information about edition upgrades, see the Version and Edition Upgrades topic in SQL Server 2005 Setup Help or SQL Server 2005 Books Online.

Other Options

Considered other options…

SQL Server Data Tools (SSDT) – BI

SSDT-BI Version SQL Server Engine Version Supported Link
SSDT-BI for Visual Studio 2015 SQL Server 2016, SQL Server 2014, SQL Server 2012, SQL Server 2008 and 2008 R2 Link
SSDT-BI for Visual Studio 2013 SQL Server 2014, SQL Server 2012, SQL Server 2008 and 2008 R2 Link
SSDT-BI for Visual Studio 2012 SQL Server 2014, SQL Server 2012, SQL Server 2008 and 2008 R2 Link

 

 

Unfortunately, SQL Server 2005 does not seem to be supported by any of the available versions of SSDT-BI.

 

Microsoft® SQL Server – Express Edition

Version SQL Server Engine Version Supported Link
Microsoft® SQL Server® 2008 R2 SP2 – Express Edition v2008, v2008/R2 Link

 

 

 

Did not check whether one can target v2005 engine…Just wanted to include for completeness.

 

SQL Server Express Edition Toolkit

Version SQL Server Engine Version Supported Link
v2005 v2005 Link

 

We can see that it appears that “Microsoft SQL Server 2005 Express Edition Toolkit” supports SQL Server v2005.

 

Downloaded

Downloaded v2005 Express Edition Toolkit from here.

Installation

Feature Selection

featureselection

 

Successfully installed the software.

Experience

Able to successfully create Reports.

References

Microsoft

  1. Developer Network – SQL Server Tools Download SQL Server Data Tools \ Download SQL Server Data Tools (SSDT)
    Link
  2. Developer Network – SQL Server Tools Download SQL Server Data Tools \ Previous releases of SQL Server Data Tools (SSDT and
    Link

 

Blogs

  1. PMAN’s LAB
    Link

SQL Server Data Tools – Error Message – Select permission denied on the object ‘certificates’, database ‘mssqlsystemresource’, schema ‘sys’.

Background

Trying to run SQL Server Data Tools with a low privileged user and ran into this problem.

 

Error Message

Image

ErrorList

 

Text

Error Messages
Warning The login for the target does not have the VIEW ANY DEFINITION permission. The comparison will be restricted to database scoped elements if the source is a database.
 The SELECT permission was denied on the object ‘certificates’, database ‘mssqlsystemresource’, schema ‘sys’.
 The SELECT permission was denied on the object ‘symmetric_keys’, database ‘mssqlsystemresource’, schema ‘sys’.

 

 

Remediation

Error – View any definition

To fix the “View any definition warning” we will issue:


use master
go

Grant VIEW ANY DEFINITION to [user];
go

Error – Select

The “The SELECT permission was denied on the object ‘certificates’, database ‘mssqlsystemresource’, schema ‘sys’.” was far more perplexing.

Capture SQL Generated by SSDT

Here is the SQL Sent by SSDT.


select 
    certificate_id id,
    null as id2,
    'CERT' as type,
    name as name1,
    null as name2,
    null as name3,
    principal_id as a1,
    binary_checksum(pvt_key_encryption_type, thumbprint) as v1,
    null as mod
from sys.certificates

Investigate Permission Set on sys.certificates

Code


exec sp_helprotect 'sys.certificates'

Output:

sp_helpprrotect-certificates

 

Grant select on sys.certificates

Code


grant select on sys.certificates to [ssdtuser];

Review Permission select on sys.certificates

Code


exec sp_helprotect 'sys.certificates'

Output:

sp_helpprrotect-certificates-postgrant

Explanation:

  1. Can’t show my user name, but believe me it is the entry #4.  And, it has a grant next to it

 

Tried running ssdt

Tried running ssdt again, but same problem.

 

Root of Problem

The root of the problem is that deny unlike revoke privilege is an enduring refuse.

Though, we granted select permission, any encompassing deny will mute our grant.

To fix


revoke select on sys.certificates from public
go

Explanation:

  1. Unfortunately, to me, using the same command, revoke, to deny and deactivate the denial is not nearly as intuitive as it could be
  2. But, it works

 

Again, Review Permission select on sys.certificates

Code


exec sp_helprotect 'sys.certificates'

Output:

sp_helpprrotect-certificates-postrevokedeny

Explanation:

  1. We rid ourselves of the deny on public group

 

Quick Summary

There is a bit of difference between Deny and Revoke.

The sysadmin user, sa, hides some of the differences.

But, once you try to use less privileged users, you might find that you have to relax enduring denials.

SQL Server Data Tools – SQL Server Data Tools Preview in Visual Studio 2015 – v14.0.23107.0 D14REL

Prelude

Need to compare schema between Production and Development database.

Checked online and did not find a free version.

And, so yet again default to SQL Server Data Tools.

It is free and last time I checked it is capable.

Here is a quick update.

 

Download

Visited SSDT download page from https://msdn.microsoft.com/en-us/library/mt204009.aspx/

The current preview is “SQL Server Data Tools Preview in Visual Studio 2015“.  And, that is available at https://msdn.microsoft.com/en-us/mt429383.

 

ISO Image Versus Administrative Install Point

ISO Image

Setup Progress – Download Progress – Installation Progress – Microsoft Visual Studio 2005 Shell ( Isolated )

We initially chose the ISO Image, but got stuck during the download process.

stuckATDownloadProgress

Administrative Install Point

And, so we went back and chose the Administrative Install Point.

Our language is English and the link for that language is http://go.microsoft.com/fwlink/?LinkID=722478&clcid=0x409.

 

Extract ISO

Using 7-Zip, we extracted the ISO image.

Select ISO Image

ListISOFiles

Extract ISO Image

ExtractISO

 

Extract Administrative Point


SSDTSetup.exe /layout extracts

 

Installation

Install Tools for these SQL Server Features

InstallToolsForTheseSQLServerFeatures

 

License Terms

LicenseTerms

 

 

Install Tools – Microsoft .Net Framework 4.6.1

InstallProgress-Microsoft-Framework-v4.6.1

 

Setup Progress

DownloadProgress-20160229-0539PM

Setup Successful
SetupSuccessful

Usage

Loading User Settings

loadingUserSettings

 

 

Schema Compare Options

 

Option Message Implication Choice
Allow Incompatible Platform A project which specifies SQL Server 2012 as the target platform cannot be published to SQL Server 2008. Turning this option on will allow one to compare schemas across various versions of SQL Server. Yes
Ignore authorizers Yes
Ignore DML Trigger Order Use sp_settriggerorder to adjust trigger firing order. Yes
Ignore Filegroup to which an object belongs When selected the Filegroups where tables, keys, indexes, and partitions are placed is ignored Yes
Ignore Fillfactor Index Fill factors on Indexes are ignored Yes
Ignore Not for replication Not for replication designations on Triggers, Constraints, and Identities are ignored.
Please read more here.
Yes
Ignore with nocheck on check constraints  Specifies whether differences in the value of the WITH NOCHECK clause for check constraints will be ignored or updated when you publish to a database No

 

Options – Differences

We will highlight a few differences we found:

  1. Login
    • User
      • Different User creation option ( without login )
  2. Table
    • Columns Order
    • Constraint
      • Foreign Key
        • Marked for replication
    • Indexes
      • Created on Filegroup
      • Different Properties
        • Included Columns
  3. Certificate
    • Create Date

Schema Compare Option

Ignore column order

Findings

StructuralDifferences-BasedOnColumnOrder

 

Explanation

  1. On the Left Side, the last 3 columns are Priority, record_created, and record_last_updated
  2. On the right side, the last 3 columns are record_created, record_last_updated, and Priority

Implications

  1. Ordering of columns has implications for Clients applications that access the recordset via column identifiers such as 0,1.  But, obviously not applications that reference via column names

Current State

This option is not currently available.

SchemaCompareOptions-IgnoreColumnOrder-Missing

Connect Item

  1. SSDT DACPAC deploy add setting back in for IgnoreColumnOrder
    1. ID 1221587
    2. Opened by: sovereignlizard
    3. Opened On: 2015.04.02
    4. Status : Active

 

Blogs & QA Item

  1. New Advanced Publish Options to Specify Object Types to Exclude or Not Drop ( by Steven Green )
    • Blog
    • Rich says”For the love all that is holy can we PLEASE get IgnoreColumnOrder back into SSDT? You’re missing out on a ton of adoption with people who have legacy databases that have been around for years (10+) with multiple installs and column orders different in all of them depending on when initially stood up. To be able to use the DAC paradigm we need to transition, sometimes slowly, starting off with tools like sqlpackage and using it for schema deltas. I much rather would be able to use a sqlproj natively than redgate.Where do we make requests that get listened to? Should it be on the SQL connect site? There are quite a few threads on this issue and none seem to be listened to.Here’s the most “active” one with plenty of upvotes:social.msdn.microsoft.com/…/schema-comparisons-ignore-column-order
  2. SQLPackage.EXE option to Ignore Column Order is Missing
    • Q/A
    • In the release-candidate version of SQL Server 2012 and SQL Server Data Tools, the
      SqlPackage.exe had an option to ingore column order when generating a deployment report.However, in the RTM version, this option is no longer present.http://msdn.microsoft.com/en-us/library/hh550080(v=vs.103).aspxCan we get this option put back in? This is making my current deployment report useless as
      I can not filter these out, which I was able to do previously.Matthew

 

Differences

Logins

Create user without login

WithoutLogin

Interpretation
  1. Body Script
    • One account created without corresponding Login
    • The other with a login

 

Schema

Different Authorizers

Body

DifferenceAuthorizers.20160301

 

Interpretation
  1. In our case the marketing schema was defined without specifying the authorizer
  2. To address, please specify the authorizer
Remediation

create schema [marketing]
	authorization [dbo]
go

 

Programmable

Encrypted Objects

Body

securityDB.usp_openkey

 

Interpretation
  1. Body Script
    • When the object is encrypted on one source, but not on the other, we see the plain code on the source where it is not encrypted.  On the other hand, we have colored spaces on the Source where it is not encrypted
Remediation
Original

alter procedure [securityDB].[usp_openkey]
(
    @key sysname = null
)
-- We will be running this module under an impersonated context
WITH EXECUTE AS OWNER
as
begin



end  


Revised

alter procedure [securityDB].[usp_openkey]
(
    @key sysname = null
)
-- We will be running this module under an impersonated context
WITH EXECUTE AS OWNER, encryption
as
begin



end  


 

Property

IsEncrypted

  1. Property
    • IsEncrypted
      • The IsEncrypted property is rightfully designated where the Object is actually encrypted

 

Constraint – Foreign Constraint

Marked for Replication

FK_Student_Violation_Student

 

Indexes

Create Indexes on specific filegroup

IND_BANNERLOG_TIME

 

Create Indexes on specific filegroup
  1. In the same above, the indexes are created on different filegroups

Create Indexes with different attributes

dbo.AdvPatrnersAssignedZipCodes-Differences

Explanation
  1. Included Columns
    • Different Included Columns
  2. Fill Factor
    • One with Fillfactor 80, the other does not have fillfactor.
    • When FillFactor not specified, we keep default of 100

 

Certificate

Difference Start Date

 certificateDate-1146AM

 

Syntax Change

To get favorable comparison, create a certificate with full syntax.

Here is a sample:


begin tran

   CREATE CERTIFICATE [certEnc]
   AUTHORIZATION [dbo]
   WITH 
	 SUBJECT = N'PIA Data'
       , START_DATE = N'2015-01-01'
       , EXPIRY_DATE = N'2016-04-24T11:23:17'
    ;
	
rollback tran

go

Explanation

  1. Start Date
    • Is the date on which the certificate becomes valid. If not specified, START_DATE will be set equal to the current date.
  2. End Date
    • Is the date on which the certificate expires.
    • If not specified, EXPIRY_DATE will be set to a date one year after START_DATE.
      however, expiration is not enforced when the certificate is used for encryption.
    • As we using for encryption, the end date is immaterial.

 

Ignore Login SIDs

Classic

The classic issue is that database SIDs are arbitrary as they tied to login SID on individual SQL Instances.

To determine differences one will issue a script such as the following

Code

select 
	  tblSU.[name]
	, tblSU.[sid]
	, tblSUR.[sid]

from   sys.sysusers tblSU

inner join [DEV].[csTrafficSchool].sys.sysusers tblSUR

	on tblSU.[name] = tblSUR.[name]

--Only get users
where tblSU.[gid] = 0
and   tblSU.[issqlrole] = 0

and   tblSU.[hasdbaccess] = 1

and
	(

		--where sid is different
		( tblSU.sid != tblSUR.sid )

	)

Publish Database

The sample provided above is the classic case.

The more pertinent thought is that this does apply when  comparing databases, but more forward thinking.  That is, when reconciling and publishing solution.

MS write-up is

Ignore login SIDs (ignore_login_sids) – Specifies whether differences in the security identification number (SID) should be ignored or updated when you publish to a database.

Here is how it is implemented

 


CREATE LOGIN TestLogin 
WITH 
       PASSWORD = 'SuperSecret52&&'
     , SID = 0x241C11948AEEB749B0D22646DB1A19F2;

Group Results

Differences can be grouped and displayed in one of the following choices:

  1. Action
  2. Schema
  3. Type

Action

  1. When Action is chosen, results are displayed as Delete, Change, and Add
  2. The delete branch contains objects in the 2nd Source, but not in the first Source

Delete

GroupByAction-Delete

Change

GroupByAction-Change

The Change grouping tags the differences between the two nodes.

Add

GroupByAction-Add

The Add branch list objects that in the first source, but not in secondary source.

Schema

Choosing schema bunches up the objects into their corresponding schemas.

GroupBySchema

 

Types

Suggestively, Types is sub-level for encompassing objects into their various object types.

GroupByType

 

Show Equal Objects

ShowEqualObjects-Icon

When Show Equal Objects is chosen, all objects are detailed.

Otherwise, only the objects that are actually different are listed.

Show Equal Objects – On

ShowEqualObjects-On

Show Equal Objects – Off

ShowEqualObjects-Off

References

  1. Options

Summary

SQL Server Data Tools is free and very granular in its approach.

There are some areas missing:

  1. One is not able to compile and package the generated code
  2. A packaged report can not be generated

SQL Server Data Tools (SSDT) / SSRS – Report Data Pane

Background

I am feeling a bit out of place with SQL Server Data Tools ( SSDT ).  Windows are missing.

 

Window Missing

reportDataPaneMissing

 

What is missing?

You never know what you have till it is gone.

Here is what our screen currently looks like.

 

reportDataPaneAppear

 

Later, find out that the window missing is called “Report Data”.

 

Report Data

Enable

To enable the “Report Data” pane.

  • Access the menu Items – View \ ReportData
  • Please keep in mind that once the Report Data panel is visible, the aforementioned menu item is gone

 

reportDataPaneMenu

 

 

What is in the “Report Data” pane:

  • List of Report Parameters
  • List of Images
  • List of Data Sources
  • List of Datasets

Basically, it contains all the elements that are currently in-use in the report.

 

SQL Server Reporting Services [SSRS] – Error – Null is not declared. ‘Null’ constants is no longer supported; use ‘System.DBNull’ instead

Background

It is a little bit of work to use null-able arguments in Sql Server Reporting Services (SSRS).

 

In DataSet Properties, Tried using “=(Null)”

For the dataset, when we set the parameter value to =Null

DatasetProperties-Parameters-(Null)

 

 Textual:

Error - Null is not declared.  'Null' constants is no longer supported; use 'System.DBNull' instead
Image:

NullConstantIsNoLongerSupported

 

In Dataset Properties, tried using “System.DBNull”

In Dataset properties, When we set the parameter value to =System.DBNull

DatasetProperties-Parameters-System.DBNull

Text
Error: [BC30691] 'DBNull' is a type in 'System' and cannot be used as an expression.

Image:
DBNullIsATypeInSystemAndCannotBeUsedInAnExpression

In Dataset Properties, tried using “=Nothing”

Tried setting the parameter value to:

  • =Nothing
  • =System.Convert.DBNull

 

DatasetProperties-Parameters-Nothing

 

We get an error.

Error

In Designer, when trying to preview the report.

Textual:

One or more parameters required to run the report have not been specified

 

Image:

OneOrMoreParametersRequiredToRunTheReportHaveNotBeenSpecified


 

Report Parameter – Default Value – Setting Parameter Value

  • Access the parameter
  • Access the “Default Values” panel
  • In the “Default Values” panel
    • In “Select from one of the following options” radio group, choose the “Specify values” option
    • In “Value” set “(Null)

ReportParameter-DefaultValues-SpecifyValues-Value-(Null)

 

Does not help

Dataset Properties – Report Parameter

Let us remove the parameter

Original:

Here are the dual parameters.

DatasetProperties-Parameter-Null-Included

Revised:

We have removed the second parameter.

DatasetProperties-Parameter-Null-Excluded

Error Message:

OneOrMoreParametersRequiredToRunTheReportHaveNotBeenSpecified (2nd Parameter removed)

Report Parameter – Set Value to Empty

Let us go set the parameter’s value to “” or System.String.Empty.

DatasetProperties-Parameter-SetToEmptyString

Things are good.

SQL Server Profiler

Here is what we see in SQL Server Profiler:

SQLServerProfiler-ParameterValueToEmpty

Transact SQL

In Transact SQL, make sure of the following:

    • The arguments is nullable — (variable [datatype] = null )
    • That you have same code line for when the variable is null and empty

 Sample Code:


if object_id('[dbo].[usp_city]') is null
begin

    exec('create procedure [dbo].[usp_city] as select 1/0 as [shell] ')

end
go

alter procedure [dbo].[usp_city]
(
      -- make sure @countryCode is nullable
      @countryCode varchar(255) = null

     --make sure that @country is nullable
    , @country     varchar(255) = null
)
as

    select
              vc.country
            , vc.countryCode
            , vc.city

    from   [dbo].[vw_city] vc

    where  (

                (
                    vc.countryCode
                                = case
                                        when (@countryCode is null) then vc.countryCode
                                        when (@countryCode = '') then vc.countryCode
                                        else @countryCode
                                  end
                )

                and
                (
                    vc.country
                                = case
                                        when (@country is null) then vc.country
                                        when (@country = '') then vc.country
                                        else @country
                                  end
                )

           ) 

    order by
                  vc.country asc
                , vc.city

go

 

Conclusion

It appears that SSRS does not really support the setting of parameters to Null, but it supports empty string.

 

References

SSRS

SQL Server Reporting Services–Error Message–“Invalid value ‘Outside’ for the custom attribute ‘Outside’”

Background

Here I am working on some reports and I ended up with the error message:

      Invalid value ‘Outside’ for the custom attribute ‘Outside’

How did I get that far off line

While waiting for my next train, I just ran into my play sister.  As we spoke the question of whether her parents are strict came up.

And, she replied “Ain’t all Caribbean parents like that”.

So here is my take, my graph used to look like this.

ActivitiesByRoom

It is obviously a Column Chart; on the other hand, it might not be so obvious that in some cases the labels will be placed inside the bars; while in

other cases they will be placed outside.

In our captured graph, our data points are shown inside for the first two numbers; 246 and 244.

SSRS Version

To keep this honest, we are developing using SQL Server Data Tools – v2012 ( SP1-CU4).

MicrosoftSQLServerReportingServicesDesigners

Setting Chart Label’s Position Outside

For the sake of consistency, let us go set the label’s position to always be on the outside.

ChartData.Legend.Label.Position

Error Message

The error message below is shown where the graph should have appeared

InvalidValueOutsideForTheCustomAttributeOutside

Remediate

To remediate, please run back and revert to Automatic.

The proper trail to take is to set via “Custom Attributes”:

CustomAttributes

Available Styles

Within the label style drop-down, here are the available choices:

CustomAttributeStyles

We can see that the disallowed choice of “Outside” is not included.

Pie Line Style

One of the cases where the Outside Position is valid, is when the graph’s type is Pie.

Custom Attributes:

For Pie Charts, the Label’s position is called “PieLabelStyle”.

Properties-PieChart-Series-Attributes

Choices:

PieLineStyle

Source Code

Here is the Source Code:

SourceCode-XML-ChartDataLabel-Position-Outside

Quick Explanation:

  • Label Position is set through the
    • Chart Series \ Label \ Position property, it is stored in ChartDataLabel \Style\ Position element
    • Chart Series \ CustomAttributes \ LabelStyle property, it is stored in ChartDataLabel \Style\ Position element

References

Listening

All the years, I have been listening to this song….  And, it is only now that I heard this line (at the very end of the song)!

Lyrics

Somethings that happen, you never really know,

Just like it says in the bible, it happens for a reason

You got to have faith

Video

Where will you be Today
http://www.vevo.com/watch/kenny-chesney/Who-Youd-Be-Today/USBVA0500022

Summary

I think back to my sister’s wise words:

Yes, I agree with my Dad.  After seeing all the problems other kids have, I like the fact that my parents are more structured

Enough about her.

I really would not have had my problems if I had gone about setting the Label Position \ Style via the more concise trail of “Custom Attributes”.

Notwithstanding what all the kids gang up to say, “more is not always better“.