Table of Contents

Class SqlServerConnectionStore

Namespace
ItTiger.TigerQuery.Core
Assembly
ItTiger.TigerQuery.Core.dll
Persists named SQL Server connection profiles as an indented JSON array in one selected file.
public sealed class SqlServerConnectionStore
Inheritance
SqlServerConnectionStore
Inherited Members

Remarks

Every operation uses the file named by the options this instance was constructed with, resolved once to an absolute path and exposed as FilePath. Nothing in the store probes another location or falls back to a default when the selected file is missing, malformed, or inaccessible: an application that selects a store selects it for lookup, filtering, copy, add, update, save, and delete alike. There is deliberately no universal default store; a host chooses Shared(string, string), AppSpecific(string, string, string), or an explicit FilePath once and injects the resulting instance everywhere.

Mutating operations (Add(SqlServerConnectionProfile), AddOrUpdate(SqlServerConnectionProfile), Copy(string, SqlServerConnectionCopyOptions, SqlServerConnectionValidationPolicy?), Delete(string), and Save(IEnumerable<SqlServerConnectionProfile>)) are coordinated by normalized path and replace the file in one step. Concurrent mutations therefore cannot lose one another's updates within a process, and a mutation that fails leaves the previous file intact rather than truncated. See MutationTimeout for the wait budget and the guarantee's exact boundaries. Reads are not coordinated because the atomic replacement never exposes a partially written file.

Returned profiles are detached mutable objects, so changes require an explicit AddOrUpdate(SqlServerConnectionProfile) or Save(IEnumerable<SqlServerConnectionProfile>) call.

Existing JSON without metadata remains compatible. Empty metadata is omitted, and metadata keys are written in ordinal order.

Constructors

SqlServerConnectionStore(SqlServerConnectionStoreOptions)

Initializes a store with the platform-default password protector.
public SqlServerConnectionStore(SqlServerConnectionStoreOptions options)

Parameters

options SqlServerConnectionStoreOptions
The JSON file location.

Exceptions

ArgumentNullException
options is null.

SqlServerConnectionStore(SqlServerConnectionStoreOptions, IConnectionPasswordProtector)

Initializes a store with an explicit password strategy.
public SqlServerConnectionStore(SqlServerConnectionStoreOptions options, IConnectionPasswordProtector passwordProtector)

Parameters

options SqlServerConnectionStoreOptions
The JSON file location.
passwordProtector IConnectionPasswordProtector
The strategy invoked around serialization and deserialization.

Exceptions

ArgumentNullException
options or passwordProtector is null.

Properties

FilePath

Gets the absolute path of the JSON file this store operates on.
public string FilePath { get; }

Property Value

string

Remarks

The path is normalized once during construction, so a relative FilePath is resolved against the working directory at that moment rather than at each call. Diagnostics and tests can use this value to prove which store an operation used; it names a file and never reveals profile contents or secrets.

Methods

Add(SqlServerConnectionProfile)

Adds a new connection. Throws when a connection with the same name already exists; this is a pure add, not an upsert.
public void Add(SqlServerConnectionProfile connection)

Parameters

connection SqlServerConnectionProfile
The profile to append.

Remarks

Profile-name matching is ordinal and case-sensitive.

Exceptions

ArgumentNullException
connection is null.
InvalidOperationException
A profile with exactly the same Name already exists.
TimeoutException
Mutation coordination for FilePath could not be acquired within MutationTimeout.

AddOrUpdate(SqlServerConnectionProfile)

Replaces every exactly named profile and appends the supplied profile.
public void AddOrUpdate(SqlServerConnectionProfile connection)

Parameters

connection SqlServerConnectionProfile
The profile to persist.

Remarks

Matching is ordinal and case-sensitive. Replacement moves the profile to the end of store order.

Exceptions

ArgumentNullException
connection is null.
TimeoutException
Mutation coordination for FilePath could not be acquired within MutationTimeout.

Copy(string, SqlServerConnectionCopyOptions, SqlServerConnectionValidationPolicy?)

Copies an existing profile inside this store under a new name, preserving every persisted setting that is not explicitly overridden.
public SqlServerConnectionProfile Copy(string sourceName, SqlServerConnectionCopyOptions options, SqlServerConnectionValidationPolicy? validationPolicy = null)

Parameters

sourceName string
The nonblank, case-sensitive name of the profile to copy.
options SqlServerConnectionCopyOptions
The target name and the controlled overrides to apply.
validationPolicy SqlServerConnectionValidationPolicy
The policy the resulting profile is validated against; DatabaseOptional when null.

Returns

SqlServerConnectionProfile
The detached profile exactly as it was persisted. It can be resolved, edited, and later removed through the ordinary Find(string), AddOrUpdate(SqlServerConnectionProfile), and Delete(string) APIs.

Remarks

The operation is same-store by construction: it is an instance method with no destination parameter, so a copy cannot silently cross stores. Source lookup, duplicate-name detection, validation, and persistence all happen while one mutation scope is held, so a concurrent mutation cannot slip a conflicting name in between the check and the write.

The copy is taken from the at-rest representation, so the source's protected password is duplicated exactly as stored. The password is never decrypted, reconstructed, logged, or handed to the caller as plaintext, and the copy succeeds even when the current user cannot decrypt the blob; whether the copy is usable afterwards follows the normal resolver and protector behavior. Neither the source nor any unrelated profile is re-protected, so their stored ciphertext is unchanged.

Every persisted field is carried by the profile's own JSON contract rather than a hand-written property list, so a field added in a later release is copied without a caller change. Overrides are limited to the profile name, the initial catalog, and the named metadata entries; all other metadata is preserved. Copy is never an upsert and never opens a SQL connection.

Exceptions

ArgumentException
sourceName is null, empty, or whitespace (parameter name sourceName), or options has a blank target name or invalid metadata mutations (parameter name options).
ArgumentNullException
options is null.
InvalidOperationException
The source profile does not exist, a profile already uses TargetName, or the resulting profile fails validation. The store is left unchanged in every case.
TimeoutException
Mutation coordination for FilePath could not be acquired within MutationTimeout.

Delete(string)

Deletes every profile with an exact name match.
public bool Delete(string name)

Parameters

name string
The nonblank, case-sensitive profile name.

Returns

bool
true when at least one profile was deleted.

Remarks

The file is rewritten only when a profile is removed.

Exceptions

ArgumentException
name is null, empty, or whitespace. The parameter name is name.
TimeoutException
Mutation coordination for FilePath could not be acquired within MutationTimeout.

Exists(string)

Determines whether an exactly named profile exists.
public bool Exists(string name)

Parameters

name string
The nonblank, case-sensitive profile name.

Returns

bool
true when a matching profile exists.

Exceptions

ArgumentException
name is null, empty, or whitespace. The parameter name is name.

Find(string)

Finds the first exactly named profile.
public SqlServerConnectionProfile? Find(string name)

Parameters

name string
The nonblank, case-sensitive profile name.

Returns

SqlServerConnectionProfile
A detached mutable profile, or null when absent.

Exceptions

ArgumentException
name is null, empty, or whitespace. The parameter name is name.

GetConnectionNamesAsync(CancellationToken)

Loads profile names in store order for provider-based selection.
public Task<IReadOnlyList<string>> GetConnectionNamesAsync(CancellationToken _)

Parameters

_ CancellationToken
A compatibility cancellation token; the current synchronous file load does not observe it.

Returns

Task<IReadOnlyList<string>>
A task containing a read-only list of profile names.

Load()

Loads and unprotects all profiles in store order.
public IReadOnlyList<SqlServerConnectionProfile> Load()

Returns

IReadOnlyList<SqlServerConnectionProfile>
A newly materialized list, or an empty list when the file does not exist or contains JSON null.

Remarks

Each loaded profile is passed to the configured password protector.

QueryByMetadata(IEnumerable<SqlServerConnectionMetadataFilter>)

Returns profiles matching every supplied metadata filter, preserving store order. Keys and values are compared ordinally and case-sensitively.
public IReadOnlyList<SqlServerConnectionProfile> QueryByMetadata(IEnumerable<SqlServerConnectionMetadataFilter> filters)

Parameters

filters IEnumerable<SqlServerConnectionMetadataFilter>
The metadata predicates combined using AND semantics.

Returns

IReadOnlyList<SqlServerConnectionProfile>
Matching detached profiles in their persisted order.

Remarks

An empty filter collection returns all profiles. Equals requires the key to exist with the exact value; IsSet requires the key to exist even when its value is empty; IsNotSet requires absence.

Exceptions

ArgumentNullException
filters is null. The parameter name is filters.
ArgumentException
A filter entry is null, has an empty key or unsupported operator, lacks a value for Equals, or supplies a value for IsSet/IsNotSet. The parameter name is filter.

Save(IEnumerable<SqlServerConnectionProfile>)

Protects and writes a complete replacement profile collection.
public void Save(IEnumerable<SqlServerConnectionProfile> connections)

Parameters

connections IEnumerable<SqlServerConnectionProfile>
The profiles to persist in enumeration order.

Remarks

The sequence is materialized once. The configured protector may mutate password fields on the supplied profile objects before serialization. Missing parent directories are created, and the file is replaced atomically under the store's mutation coordination.

Exceptions

ArgumentNullException
connections is null.
TimeoutException
Mutation coordination for FilePath could not be acquired within MutationTimeout.