Added options to connection parameter (#285)

* Added options to connection parameter
This commit is contained in:
Leila Lali
2017-03-21 13:22:29 -07:00
committed by GitHub
parent addad29b7c
commit 9e576dea92
5 changed files with 788 additions and 63 deletions

View File

@@ -15,6 +15,13 @@ namespace Microsoft.SqlTools.Hosting.Contracts
public ConnectionOption[] Options { get; set; }
}
public class CategoryValue
{
public string DisplayName { get; set; }
public string Name { get; set; }
}
public class ConnectionOption
{
public static readonly string ValueTypeString = "string";
@@ -48,10 +55,10 @@ namespace Microsoft.SqlTools.Hosting.Contracts
/// <summary>
/// Set of permitted values if ValueType is category.
/// </summary>
public string[] CategoryValues { get; set; }
public CategoryValue[] CategoryValues { get; set; }
/// <summary>
/// Determines if the parameter is one of the 'specical' known values.
/// Determines if the parameter is one of the 'special' known values.
/// Can be either Server Name, Database Name, Authentication Type,
/// User Name, or Password
/// </summary>

View File

@@ -3,6 +3,8 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System.Collections.Generic;
namespace Microsoft.SqlTools.ServiceLayer.Connection.Contracts
{
/// <summary>
@@ -13,120 +15,457 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.Contracts
/// </remarks>
public class ConnectionDetails : ConnectionSummary
{
public ConnectionDetails()
{
Options = new Dictionary<string, object>();
}
/// <summary>
/// Gets or Sets the connection options
/// </summary>
public Dictionary<string, object> Options { get; set; }
/// <summary>
/// Gets or sets the connection password
/// </summary>
/// <returns></returns>
public string Password { get; set; }
public string Password {
get
{
return GetOptionValue<string>("password");
}
set
{
SetOptionValue("password", value);
}
}
/// <summary>
/// Gets or sets the connection server name
/// </summary>
public override string ServerName
{
get
{
return GetOptionValue<string>("server");
}
set
{
SetOptionValue("server", value);
}
}
/// <summary>
/// Gets or sets the connection database name
/// </summary>
public override string DatabaseName
{
get
{
return GetOptionValue<string>("database");
}
set
{
SetOptionValue("database", value);
}
}
/// <summary>
/// Gets or sets the connection user name
/// </summary>
public override string UserName
{
get
{
return GetOptionValue<string>("user");
}
set
{
SetOptionValue("user", value);
}
}
/// <summary>
/// Gets or sets the authentication to use.
/// </summary>
public string AuthenticationType { get; set; }
public string AuthenticationType
{
get
{
return GetOptionValue<string>("authenticationType");
}
set
{
SetOptionValue("authenticationType", value);
}
}
/// <summary>
/// Gets or sets a Boolean value that indicates whether SQL Server uses SSL encryption for all data sent between the client and server if the server has a certificate installed.
/// </summary>
public bool? Encrypt { get; set; }
public bool? Encrypt
{
get
{
return GetOptionValue<bool?>("encrypt");
}
set
{
SetOptionValue("encrypt", value);
}
}
/// <summary>
/// Gets or sets a value that indicates whether the channel will be encrypted while bypassing walking the certificate chain to validate trust.
/// </summary>
public bool? TrustServerCertificate { get; set; }
public bool? TrustServerCertificate
{
get
{
return GetOptionValue<bool?>("trustServerCertificate");
}
set
{
SetOptionValue("trustServerCertificate", value);
}
}
/// <summary>
/// Gets or sets a Boolean value that indicates if security-sensitive information, such as the password, is not returned as part of the connection if the connection is open or has ever been in an open state.
/// </summary>
public bool? PersistSecurityInfo { get; set; }
public bool? PersistSecurityInfo
{
get
{
return GetOptionValue<bool?>("persistSecurityInfo");
}
set
{
SetOptionValue("persistSecurityInfo", value);
}
}
/// <summary>
/// Gets or sets the length of time (in seconds) to wait for a connection to the server before terminating the attempt and generating an error.
/// </summary>
public int? ConnectTimeout { get; set; }
public int? ConnectTimeout
{
get
{
return GetOptionValue<int?>("connectTimeout");
}
set
{
SetOptionValue("connectTimeout", value);
}
}
/// <summary>
/// The number of reconnections attempted after identifying that there was an idle connection failure.
/// </summary>
public int? ConnectRetryCount { get; set; }
public int? ConnectRetryCount
{
get
{
return GetOptionValue<int?>("connectRetryCount");
}
set
{
SetOptionValue("connectRetryCount", value);
}
}
/// <summary>
/// Amount of time (in seconds) between each reconnection attempt after identifying that there was an idle connection failure.
/// </summary>
public int? ConnectRetryInterval { get; set; }
public int? ConnectRetryInterval
{
get
{
return GetOptionValue<int?>("connectRetryInterval");
}
set
{
SetOptionValue("connectRetryInterval", value);
}
}
/// <summary>
/// Gets or sets the name of the application associated with the connection string.
/// </summary>
public string ApplicationName { get; set; }
public string ApplicationName
{
get
{
return GetOptionValue<string>("applicationName");
}
set
{
SetOptionValue("applicationName", value);
}
}
/// <summary>
/// Gets or sets the name of the workstation connecting to SQL Server.
/// </summary>
public string WorkstationId { get; set; }
public string WorkstationId
{
get
{
return GetOptionValue<string>("workstationId");
}
set
{
SetOptionValue("workstationId", value);
}
}
/// <summary>
/// Declares the application workload type when connecting to a database in an SQL Server Availability Group.
/// </summary>
public string ApplicationIntent { get; set; }
public string ApplicationIntent
{
get
{
return GetOptionValue<string>("applicationIntent");
}
set
{
SetOptionValue("applicationIntent", value);
}
}
/// <summary>
/// Gets or sets the SQL Server Language record name.
/// </summary>
public string CurrentLanguage { get; set; }
public string CurrentLanguage
{
get
{
return GetOptionValue<string>("currentLanguage");
}
set
{
SetOptionValue("currentLanguage", value);
}
}
/// <summary>
/// Gets or sets a Boolean value that indicates whether the connection will be pooled or explicitly opened every time that the connection is requested.
/// </summary>
public bool? Pooling { get; set; }
public bool? Pooling
{
get
{
return GetOptionValue<bool?>("pooling");
}
set
{
SetOptionValue("pooling", value);
}
}
/// <summary>
/// Gets or sets the maximum number of connections allowed in the connection pool for this specific connection string.
/// </summary>
public int? MaxPoolSize { get; set; }
public int? MaxPoolSize
{
get
{
return GetOptionValue<int?>("maxPoolSize");
}
set
{
SetOptionValue("maxPoolSize", value);
}
}
/// <summary>
/// Gets or sets the minimum number of connections allowed in the connection pool for this specific connection string.
/// </summary>
public int? MinPoolSize { get; set; }
public int? MinPoolSize
{
get
{
return GetOptionValue<int?>("minPoolSize");
}
set
{
SetOptionValue("minPoolSize", value);
}
}
/// <summary>
/// Gets or sets the minimum time, in seconds, for the connection to live in the connection pool before being destroyed.
/// </summary>
public int? LoadBalanceTimeout { get; set; }
public int? LoadBalanceTimeout
{
get
{
return GetOptionValue<int?>("loadBalanceTimeout");
}
set
{
SetOptionValue("loadBalanceTimeout", value);
}
}
/// <summary>
/// Gets or sets a Boolean value that indicates whether replication is supported using the connection.
/// </summary>
public bool? Replication { get; set; }
public bool? Replication
{
get
{
return GetOptionValue<bool?>("replication");
}
set
{
SetOptionValue("replication", value);
}
}
/// <summary>
/// Gets or sets a string that contains the name of the primary data file. This includes the full path name of an attachable database.
/// </summary>
public string AttachDbFilename { get; set; }
public string AttachDbFilename
{
get
{
return GetOptionValue<string>("attachDbFilename");
}
set
{
SetOptionValue("attachDbFilename", value);
}
}
/// <summary>
/// Gets or sets the name or address of the partner server to connect to if the primary server is down.
/// </summary>
public string FailoverPartner { get; set; }
public string FailoverPartner
{
get
{
return GetOptionValue<string>("failoverPartner");
}
set
{
SetOptionValue("failoverPartner", value);
}
}
/// <summary>
/// If your application is connecting to an AlwaysOn availability group (AG) on different subnets, setting MultiSubnetFailover=true provides faster detection of and connection to the (currently) active server.
/// </summary>
public bool? MultiSubnetFailover { get; set; }
public bool? MultiSubnetFailover
{
get
{
return GetOptionValue<bool?>("multiSubnetFailover");
}
set
{
SetOptionValue("multiSubnetFailover", value);
}
}
/// <summary>
/// When true, an application can maintain multiple active result sets (MARS).
/// </summary>
public bool? MultipleActiveResultSets { get; set; }
public bool? MultipleActiveResultSets
{
get
{
return GetOptionValue<bool?>("multipleActiveResultSets");
}
set
{
SetOptionValue("multipleActiveResultSets", value);
}
}
/// <summary>
/// Gets or sets the size in bytes of the network packets used to communicate with an instance of SQL Server.
/// </summary>
public int? PacketSize { get; set; }
public int? PacketSize
{
get
{
return GetOptionValue<int?>("packetSize");
}
set
{
SetOptionValue("packetSize", value);
}
}
/// <summary>
/// Gets or sets a string value that indicates the type system the application expects.
/// </summary>
public string TypeSystemVersion { get; set; }
public string TypeSystemVersion
{
get
{
return GetOptionValue<string>("typeSystemVersion");
}
set
{
SetOptionValue("typeSystemVersion", value);
}
}
private T GetOptionValue<T>(string name)
{
T result = default(T);
if (Options != null && Options.ContainsKey(name))
{
object value = Options[name];
if(value != null && ( typeof(T) == typeof(int) || typeof(T) == typeof(int?)))
{
value = System.Convert.ToInt32(value);
}
result = value != null ? (T)value : default(T);
}
return result;
}
private void SetOptionValue<T>(string name, T value)
{
Options = Options ?? new Dictionary<string, object>();
if (Options.ContainsKey(name))
{
Options[name] = value;
}
else
{
Options.Add(name, value);
}
}
}
}

View File

@@ -13,16 +13,16 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.Contracts
/// <summary>
/// Gets or sets the connection server name
/// </summary>
public string ServerName { get; set; }
public virtual string ServerName { get; set; }
/// <summary>
/// Gets or sets the connection database name
/// </summary>
public string DatabaseName { get; set; }
public virtual string DatabaseName { get; set; }
/// <summary>
/// Gets or sets the connection user name
/// </summary>
public string UserName { get; set; }
public virtual string UserName { get; set; }
}
}

View File

@@ -190,7 +190,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Hosting
);
}
private static ConnectionProviderOptions BuildConnectionProviderOptions()
internal static ConnectionProviderOptions BuildConnectionProviderOptions()
{
return new ConnectionProviderOptions
{
@@ -198,110 +198,278 @@ namespace Microsoft.SqlTools.ServiceLayer.Hosting
{
new ConnectionOption
{
Name = "Server Name",
Name = "server",
DisplayName = "Server Name",
Description = "Name of the SQL Server instance",
ValueType = ConnectionOption.ValueTypeString,
SpecialValueType = ConnectionOption.SpecialValueServerName,
IsIdentity = true,
IsRequired = true
IsRequired = true,
GroupName = "Source"
},
new ConnectionOption
{
Name = "Initial Catalog",
Name = "database",
DisplayName = "Database Name",
Description = "Name of the SQL Server database",
Description = "The name of the initial catalog or database int the data source",
ValueType = ConnectionOption.ValueTypeString,
SpecialValueType = ConnectionOption.SpecialValueDatabaseName,
IsIdentity = true,
IsRequired = true
IsRequired = true,
GroupName = "Source"
},
new ConnectionOption
{
Name = "Auth Type",
Description = "Authentication type",
Name = "authenticationType",
DisplayName = "Authentication Type",
Description = "Specifies the method of authenticating with SQL Server",
ValueType = ConnectionOption.ValueTypeCategory,
SpecialValueType = ConnectionOption.SpecialValueAuthType,
CategoryValues = new string[] { "SQL Login", "Integrated Auth" },
CategoryValues = new CategoryValue[]
{ new CategoryValue {DisplayName = "SQL Login", Name = "SqlLogin" },
new CategoryValue {DisplayName = "Integrated Auth", Name= "Integrated" }
},
IsIdentity = true,
IsRequired = true
IsRequired = true,
GroupName = "Security"
},
new ConnectionOption
{
Name = "Username",
Description = "SQL Login user name",
Name = "user",
DisplayName = "User Name",
Description = "Indicates the user ID to be used when connecting to the data source",
ValueType = ConnectionOption.ValueTypeString,
SpecialValueType = ConnectionOption.SpecialValueUserName,
IsIdentity = true,
IsRequired = true
IsRequired = true,
GroupName = "Security"
},
new ConnectionOption
{
Name = "Password",
Description = "SQL Login password",
Name = "password",
DisplayName = "Password",
Description = "Indicates the password to be used when connecting to the data source",
ValueType = ConnectionOption.ValueTypePassword,
SpecialValueType = ConnectionOption.SpecialValuePasswordName,
IsIdentity = true,
IsRequired = true
IsRequired = true,
GroupName = "Security"
},
new ConnectionOption
{
Name = "Application Intent",
Description = "Application intent",
Name = "applicationIntent",
DisplayName = "Application Intent",
Description = "Declares the application workload type when connecting to a server",
ValueType = ConnectionOption.ValueTypeCategory,
CategoryValues = new string[] { "ReadWrite", "ReadOnly" }
CategoryValues = new CategoryValue[] {
new CategoryValue { Name = "ReadWrite", DisplayName = "ReadWrite" },
new CategoryValue {Name = "ReadOnly", DisplayName = "ReadOnly" }
},
GroupName = "Initialization"
},
new ConnectionOption
{
Name = "Asynchronous Processing",
Description = "Application processing enabled",
ValueType = ConnectionOption.ValueTypeBoolean
Name = "asynchronousProcessing",
DisplayName = "Asynchronous processing enabled",
Description = "When true, enables usage of the Asynchronous functionality in the .Net Framework Data Provider",
ValueType = ConnectionOption.ValueTypeBoolean,
GroupName = "Initialization"
},
new ConnectionOption
{
Name = "Connect Timeout",
Description = "Timeout in seconds when establishing a connection",
Name = "connectTimeout",
DisplayName = "Connect Timeout",
Description =
"The length of time (in seconds) to wait for a connection to the server before terminating the attempt and generating an error",
ValueType = ConnectionOption.ValueTypeNumber,
DefaultValue = "15"
DefaultValue = "15",
GroupName = "Initialization"
},
new ConnectionOption
{
Name = "Current Language",
ValueType = ConnectionOption.ValueTypeString
Name = "currentLanguage",
DisplayName = "Current Language",
Description = "The SQL Server language record name",
ValueType = ConnectionOption.ValueTypeString,
GroupName = "Initialization"
},
new ConnectionOption
{
Name = "Column Encrytion Setting",
Name = "columnEncryptionSetting",
DisplayName = "Column Encryption Setting",
Description = "Default column encryption setting for all the commands on the connection",
ValueType = ConnectionOption.ValueTypeCategory,
GroupName = "Security",
CategoryValues = new string[] { "Disabled", "Enabled" }
CategoryValues = new CategoryValue[] {
new CategoryValue { Name = "Disabled" },
new CategoryValue {Name = "Enabled" }
}
},
new ConnectionOption
{
Name = "Encrypt",
Name = "encrypt",
DisplayName = "Encrypt",
Description =
"When true, SQL Server uses SSL encryption for all data sent between the client and server if the servers has a certificate installed",
GroupName = "Security",
ValueType = ConnectionOption.ValueTypeBoolean
},
new ConnectionOption
{
Name = "Persist Security Info",
Name = "persistSecurityInfo",
DisplayName = "Persist Security Info",
Description = "When false, security-sensitive information, such as the password, is not returned as part of the connection",
GroupName = "Security",
ValueType = ConnectionOption.ValueTypeBoolean
},
new ConnectionOption
{
Name = "Trust Server Certificate",
Name = "trustServerCertificate",
DisplayName = "Trust Server Certificate",
Description = "When true (and encrypt=true), SQL Server uses SSL encryption for all data sent between the client and server without validating the server certificate",
GroupName = "Security",
ValueType = ConnectionOption.ValueTypeBoolean
},
new ConnectionOption
{
Name = "Attached DB File Name",
Name = "attachedDBFileName",
DisplayName = "Attached DB File Name",
Description = "The name of the primary file, including the full path name, of an attachable database",
ValueType = ConnectionOption.ValueTypeString,
GroupName = "Source"
},
new ConnectionOption
{
Name = "contextConnection",
DisplayName = "Context Connection",
Description = "When true, indicates the connection should be from the SQL server context. Available only when running in the SQL Server process",
ValueType = ConnectionOption.ValueTypeBoolean,
GroupName = "Source"
},
new ConnectionOption
{
Name = "port",
DisplayName = "Port",
ValueType = ConnectionOption.ValueTypeNumber
},
new ConnectionOption
{
Name = "connectRetryCount",
DisplayName = "Connect Retry Count",
Description = "Number of attempts to restore connection",
ValueType = ConnectionOption.ValueTypeNumber,
DefaultValue = "1",
GroupName = "Connection Resiliency"
},
new ConnectionOption
{
Name = "connectRetryInterval",
DisplayName = "Connect Retry Interval",
Description = "Delay between attempts to restore connection",
ValueType = ConnectionOption.ValueTypeNumber,
DefaultValue = "10",
GroupName = "Connection Resiliency"
},
new ConnectionOption
{
Name = "applicationName",
DisplayName = "Application Name",
Description = "The name of the application",
ValueType = ConnectionOption.ValueTypeString,
GroupName = "Context"
},
new ConnectionOption
{
Name = "workstationId",
DisplayName = "Workstation Id",
Description = "The name of the workstation connecting to SQL Server",
ValueType = ConnectionOption.ValueTypeString,
GroupName = "Context"
},
new ConnectionOption
{
Name = "pooling",
DisplayName = "Pooling",
Description = "When true, the connection object is drawn from the appropriate pool, or if necessary, is created and added to the appropriate pool",
ValueType = ConnectionOption.ValueTypeBoolean,
GroupName = "Pooling"
},
new ConnectionOption
{
Name = "maxPoolSize",
DisplayName = "Max Pool Size",
Description = "The maximum number of connections allowed in the pool",
ValueType = ConnectionOption.ValueTypeNumber,
GroupName = "Pooling"
},
new ConnectionOption
{
Name = "minPoolSize",
DisplayName = "Min Pool Size",
Description = "The minimum number of connections allowed in the pool",
ValueType = ConnectionOption.ValueTypeNumber,
GroupName = "Pooling"
},
new ConnectionOption
{
Name = "loadBalanceTimeout",
DisplayName = "Load Balance Timeout",
Description = "The minimum amount of time (in seconds) for this connection to live in the pool before being destroyed",
ValueType = ConnectionOption.ValueTypeNumber,
GroupName = "Pooling"
},
new ConnectionOption
{
Name = "replication",
DisplayName = "Replication",
Description = "Used by SQL Server in Replication",
ValueType = ConnectionOption.ValueTypeBoolean,
GroupName = "Replication"
},
new ConnectionOption
{
Name = "attachDbFilename",
DisplayName = "Attach Db Filename",
ValueType = ConnectionOption.ValueTypeString
},
new ConnectionOption
{
Name = "Context Connection",
ValueType = ConnectionOption.ValueTypeString
Name = "failoverPartner",
DisplayName = "Failover Partner",
Description = "the name or network address of the instance of SQL Server that acts as a failover partner",
ValueType = ConnectionOption.ValueTypeString,
GroupName = " Source"
},
new ConnectionOption
{
Name = "multiSubnetFailover",
DisplayName = "Multi Subnet Failover",
ValueType = ConnectionOption.ValueTypeBoolean
},
new ConnectionOption
{
Name = "multipleActiveResultSets",
DisplayName = "Multiple Active ResultSets",
Description = "When true, multiple result sets can be returned and read from one connection",
ValueType = ConnectionOption.ValueTypeBoolean,
GroupName = "Advanced"
},
new ConnectionOption
{
Name = "packetSize",
DisplayName = "Packet Size",
Description = "Size in bytes of the network packets used to communicate with an instance of SQL Server",
ValueType = ConnectionOption.ValueTypeNumber,
GroupName = "Advanced"
},
new ConnectionOption
{
Name = "typeSystemVersion",
DisplayName = "Type System Version",
Description = "Indicates which server type system then provider will expose through the DataReader",
ValueType = ConnectionOption.ValueTypeString,
GroupName = "Advanced"
}
}
};

View File

@@ -0,0 +1,211 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System.Linq;
using Microsoft.SqlTools.Hosting.Contracts;
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
using Xunit;
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection
{
/// <summary>
/// Tests for ConnectionDetails Class
/// </summary>
public class ConnectionDetailsTests
{
[Fact]
public void ConnectionDetailsWithoutAnyOptionShouldReturnNullOrDefaultForOptions()
{
ConnectionDetails details = new ConnectionDetails();
var expectedForStrings = default(string);
var expectedForInt = default(int?);
var expectedForBoolean = default(bool?);
Assert.Equal(details.ApplicationIntent, expectedForStrings);
Assert.Equal(details.ApplicationName, expectedForStrings);
Assert.Equal(details.AttachDbFilename, expectedForStrings);
Assert.Equal(details.AuthenticationType, expectedForStrings);
Assert.Equal(details.CurrentLanguage, expectedForStrings);
Assert.Equal(details.DatabaseName, expectedForStrings);
Assert.Equal(details.FailoverPartner, expectedForStrings);
Assert.Equal(details.Password, expectedForStrings);
Assert.Equal(details.ServerName, expectedForStrings);
Assert.Equal(details.TypeSystemVersion, expectedForStrings);
Assert.Equal(details.UserName, expectedForStrings);
Assert.Equal(details.WorkstationId, expectedForStrings);
Assert.Equal(details.ConnectRetryInterval, expectedForInt);
Assert.Equal(details.ConnectRetryCount, expectedForInt);
Assert.Equal(details.ConnectTimeout, expectedForInt);
Assert.Equal(details.LoadBalanceTimeout, expectedForInt);
Assert.Equal(details.MaxPoolSize, expectedForInt);
Assert.Equal(details.MinPoolSize, expectedForInt);
Assert.Equal(details.PacketSize, expectedForInt);
Assert.Equal(details.Encrypt, expectedForBoolean);
Assert.Equal(details.MultipleActiveResultSets, expectedForBoolean);
Assert.Equal(details.MultiSubnetFailover, expectedForBoolean);
Assert.Equal(details.PersistSecurityInfo, expectedForBoolean);
Assert.Equal(details.Pooling, expectedForBoolean);
Assert.Equal(details.Replication, expectedForBoolean);
Assert.Equal(details.TrustServerCertificate, expectedForBoolean);
}
[Fact]
public void ConnectionDetailsPropertySettersShouldSetOptionValuesCorrectly()
{
ConnectionDetails details = new ConnectionDetails();
var index = 0;
var expectedForStrings = "Value for strings";
var expectedForInt = 345;
details.ApplicationIntent = expectedForStrings + index++;
details.ApplicationName = expectedForStrings + index++;
details.AttachDbFilename = expectedForStrings + index++;
details.AuthenticationType = expectedForStrings + index++;
details.CurrentLanguage = expectedForStrings + index++;
details.DatabaseName = expectedForStrings + index++;
details.FailoverPartner = expectedForStrings + index++;
details.Password = expectedForStrings + index++;
details.ServerName = expectedForStrings + index++;
details.TypeSystemVersion = expectedForStrings + index++;
details.UserName = expectedForStrings + index++;
details.WorkstationId = expectedForStrings + index++;
details.ConnectRetryInterval = expectedForInt + index++;
details.ConnectRetryCount = expectedForInt + index++;
details.ConnectTimeout = expectedForInt + index++;
details.LoadBalanceTimeout = expectedForInt + index++;
details.MaxPoolSize = expectedForInt + index++;
details.MinPoolSize = expectedForInt + index++;
details.PacketSize = expectedForInt + index++;
details.Encrypt = (index++ % 2 == 0);
details.MultipleActiveResultSets = (index++ % 2 == 0);
details.MultiSubnetFailover = (index++ % 2 == 0);
details.PersistSecurityInfo = (index++ % 2 == 0);
details.Pooling = (index++ % 2 == 0);
details.Replication = (index++ % 2 == 0);
details.TrustServerCertificate = (index++ % 2 == 0);
index = 0;
Assert.Equal(details.ApplicationIntent, expectedForStrings + index++);
Assert.Equal(details.ApplicationName, expectedForStrings + index++);
Assert.Equal(details.AttachDbFilename, expectedForStrings + index++);
Assert.Equal(details.AuthenticationType, expectedForStrings + index++);
Assert.Equal(details.CurrentLanguage, expectedForStrings + index++);
Assert.Equal(details.DatabaseName, expectedForStrings + index++);
Assert.Equal(details.FailoverPartner, expectedForStrings + index++);
Assert.Equal(details.Password, expectedForStrings + index++);
Assert.Equal(details.ServerName, expectedForStrings + index++);
Assert.Equal(details.TypeSystemVersion, expectedForStrings + index++);
Assert.Equal(details.UserName, expectedForStrings + index++);
Assert.Equal(details.WorkstationId, expectedForStrings + index++);
Assert.Equal(details.ConnectRetryInterval, expectedForInt + index++);
Assert.Equal(details.ConnectRetryCount, expectedForInt + index++);
Assert.Equal(details.ConnectTimeout, expectedForInt + index++);
Assert.Equal(details.LoadBalanceTimeout, expectedForInt + index++);
Assert.Equal(details.MaxPoolSize, expectedForInt + index++);
Assert.Equal(details.MinPoolSize, expectedForInt + index++);
Assert.Equal(details.PacketSize, expectedForInt + index++);
Assert.Equal(details.Encrypt, (index++ % 2 == 0));
Assert.Equal(details.MultipleActiveResultSets, (index++ % 2 == 0));
Assert.Equal(details.MultiSubnetFailover, (index++ % 2 == 0));
Assert.Equal(details.PersistSecurityInfo, (index++ % 2 == 0));
Assert.Equal(details.Pooling, (index++ % 2 == 0));
Assert.Equal(details.Replication, (index++ % 2 == 0));
Assert.Equal(details.TrustServerCertificate, (index++ % 2 == 0));
}
[Fact]
public void ConnectionDetailsOptionsShouldBeDefinedInConnectionProviderOptions()
{
ConnectionDetails details = new ConnectionDetails();
ConnectionProviderOptions optionMetadata = Hosting.ServiceHost.BuildConnectionProviderOptions();
var index = 0;
var expectedForStrings = "Value for strings";
var expectedForInt = 345;
details.ApplicationIntent = expectedForStrings + index++;
details.ApplicationName = expectedForStrings + index++;
details.AttachDbFilename = expectedForStrings + index++;
details.AuthenticationType = expectedForStrings + index++;
details.CurrentLanguage = expectedForStrings + index++;
details.DatabaseName = expectedForStrings + index++;
details.FailoverPartner = expectedForStrings + index++;
details.Password = expectedForStrings + index++;
details.ServerName = expectedForStrings + index++;
details.TypeSystemVersion = expectedForStrings + index++;
details.UserName = expectedForStrings + index++;
details.WorkstationId = expectedForStrings + index++;
details.ConnectRetryInterval = expectedForInt + index++;
details.ConnectRetryCount = expectedForInt + index++;
details.ConnectTimeout = expectedForInt + index++;
details.LoadBalanceTimeout = expectedForInt + index++;
details.MaxPoolSize = expectedForInt + index++;
details.MinPoolSize = expectedForInt + index++;
details.PacketSize = expectedForInt + index++;
details.Encrypt = (index++ % 2 == 0);
details.MultipleActiveResultSets = (index++ % 2 == 0);
details.MultiSubnetFailover = (index++ % 2 == 0);
details.PersistSecurityInfo = (index++ % 2 == 0);
details.Pooling = (index++ % 2 == 0);
details.Replication = (index++ % 2 == 0);
details.TrustServerCertificate = (index++ % 2 == 0);
if(optionMetadata.Options.Count() != details.Options.Count)
{
var optionsNotInMetadata = details.Options.Where(o => !optionMetadata.Options.Any(m => m.Name == o.Key));
var optionNames = optionsNotInMetadata.Any() ? optionsNotInMetadata.Select(s => s.Key).Aggregate((i, j) => i + "," + j) : null;
Assert.True(string.IsNullOrEmpty(optionNames), "Options not in metadata: " + optionNames);
}
foreach (var option in details.Options)
{
var metadata = optionMetadata.Options.FirstOrDefault(x => x.Name == option.Key);
Assert.NotNull(metadata);
if(metadata.ValueType == ConnectionOption.ValueTypeString)
{
Assert.True(option.Value is string);
}
else if (metadata.ValueType == ConnectionOption.ValueTypeBoolean)
{
Assert.True(option.Value is bool?);
}
else if (metadata.ValueType == ConnectionOption.ValueTypeNumber)
{
Assert.True(option.Value is int?);
}
}
}
[Fact]
public void SettingConnectiomTimeoutToLongShouldStillReturnInt()
{
ConnectionDetails details = new ConnectionDetails();
long timeout = 30;
int? expectedValue = 30;
details.Options["connectTimeout"] = timeout;
Assert.Equal(details.ConnectTimeout, expectedValue);
}
[Fact]
public void ConnectTimeoutShouldReturnNullIfNotSet()
{
ConnectionDetails details = new ConnectionDetails();
int? expectedValue = null;
Assert.Equal(details.ConnectTimeout, expectedValue);
}
[Fact]
public void ConnectTimeoutShouldReturnNullIfSetToNull()
{
ConnectionDetails details = new ConnectionDetails();
details.Options["connectTimeout"] = null;
int? expectedValue = null;
Assert.Equal(details.ConnectTimeout, expectedValue);
}
}
}