From 21c3e18f432d341046efa281c74cad2e381cdd75 Mon Sep 17 00:00:00 2001
From: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com>
Date: Wed, 25 Nov 2020 12:40:24 -0800
Subject: [PATCH 001/509] Add samples (#821)
Related to the second part of porting documents from .NET Framework documents.
---
doc/samples/SqlCommandBuilder_Create.cs | 63 +++++++++++++++
.../SqlCommand_ExecuteNonQuery_SP_DML.cs | 77 +++++++++++++++++++
.../SqlCommand_ExecuteScalar_Return_Id.cs | 47 +++++++++++
doc/samples/SqlDataAdapter_FillDataSet.cs | 74 ++++++++++++++++++
doc/samples/SqlDataAdapter_SqlDataAdapter.cs | 19 ++++-
doc/samples/SqlDataReader_GetSchemaTable.cs | 54 +++++++++++++
doc/samples/SqlDataReader_HasRows.cs | 57 ++++++++++++++
doc/samples/SqlDataReader_NextResult.cs | 62 +++++++++++++++
8 files changed, 451 insertions(+), 2 deletions(-)
create mode 100644 doc/samples/SqlCommandBuilder_Create.cs
create mode 100644 doc/samples/SqlCommand_ExecuteNonQuery_SP_DML.cs
create mode 100644 doc/samples/SqlCommand_ExecuteScalar_Return_Id.cs
create mode 100644 doc/samples/SqlDataAdapter_FillDataSet.cs
create mode 100644 doc/samples/SqlDataReader_GetSchemaTable.cs
create mode 100644 doc/samples/SqlDataReader_HasRows.cs
create mode 100644 doc/samples/SqlDataReader_NextResult.cs
diff --git a/doc/samples/SqlCommandBuilder_Create.cs b/doc/samples/SqlCommandBuilder_Create.cs
new file mode 100644
index 0000000000..13322368af
--- /dev/null
+++ b/doc/samples/SqlCommandBuilder_Create.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Data;
+using Microsoft.Data.SqlClient;
+
+namespace SqlCommandBuilderCS
+{
+ class Program
+ {
+ static void Main()
+ {
+ string cnnst = "Data Source=(local);Initial Catalog=Northwind;"
+ + "Integrated Security=SSPI";
+ string queryst = "SELECT CustomerID, CompanyName, ContactName, Phone FROM Customers";
+ string newQueryString = "SELECT CustomerID, City, Region FROM Customers";
+ string tablen = "Customers";
+ DataSet ds = SelectSqlRows(cnnst, queryst, newQueryString, tablen);
+ }
+
+ public static DataSet SelectSqlRows(string connectionString,
+ string queryString, string newQueryString, string tableName)
+ {
+ using (SqlConnection connection = new SqlConnection(connectionString))
+ {
+ //
+ // Assumes that connection is a valid SqlConnection object
+ // inside of a using block.
+ SqlDataAdapter adapter = new SqlDataAdapter();
+ adapter.SelectCommand = new SqlCommand(queryString, connection);
+ SqlCommandBuilder builder = new SqlCommandBuilder(adapter);
+ builder.QuotePrefix = "[";
+ builder.QuoteSuffix = "]";
+ //
+
+ //
+ // Generate the update command automatically by SqlCommandBuilder
+ Console.WriteLine(builder.GetUpdateCommand().CommandText);
+ //
+
+ connection.Open();
+
+ DataSet dataSet = new DataSet();
+ adapter.Fill(dataSet, tableName);
+
+ //
+ // Assumes an open SqlConnection and SqlDataAdapter inside of a using block.
+ adapter.SelectCommand.CommandText = newQueryString;
+ builder.RefreshSchema();
+
+ dataSet.Tables.Remove(dataSet.Tables[tableName]);
+ adapter.Fill(dataSet, tableName);
+ //
+
+ //code to modify data in DataSet here
+ builder.GetUpdateCommand();
+
+ //Without the SqlCommandBuilder this line would fail
+ adapter.Update(dataSet, tableName);
+
+ return dataSet;
+ }
+ }
+ }
+}
diff --git a/doc/samples/SqlCommand_ExecuteNonQuery_SP_DML.cs b/doc/samples/SqlCommand_ExecuteNonQuery_SP_DML.cs
new file mode 100644
index 0000000000..6b35ce142b
--- /dev/null
+++ b/doc/samples/SqlCommand_ExecuteNonQuery_SP_DML.cs
@@ -0,0 +1,77 @@
+using System;
+using System.Data;
+using Microsoft.Data.SqlClient;
+
+namespace SqlCommandCS
+{
+ class Program
+ {
+ static void Main()
+ {
+ string str = "Data Source=(local);Initial Catalog=Northwind;"
+ + "Integrated Security=SSPI";
+
+ CreateStoredProcedure(str);
+ CreateCommand(str);
+ }
+
+ private static void CreateStoredProcedure(string connectionString)
+ {
+ using (SqlConnection connection = new SqlConnection(connectionString))
+ {
+ //
+ // Assumes connection is a valid SqlConnection.
+ string queryString = "CREATE PROCEDURE InsertCategory " +
+ "@CategoryName nchar(15), " +
+ "@Identity int OUT " +
+ "AS " +
+ "INSERT INTO Categories (CategoryName) VALUES(@CategoryName) " +
+ "SET @Identity = @@Identity " +
+ "RETURN @@ROWCOUNT";
+
+ SqlCommand command = new SqlCommand(queryString, connection);
+ command.ExecuteNonQuery();
+ //
+ }
+ }
+
+ private static void CreateCommand(string connectionString)
+ {
+ using (SqlConnection connection = new SqlConnection(connectionString))
+ {
+ SqlCommand command = new SqlCommand(connection);
+
+ //
+ // Assumes connection is a valid SqlConnection.
+ connection.Open();
+
+ string queryString = "INSERT INTO Customers " +
+ "(CustomerID, CompanyName) Values('NWIND', 'Northwind Traders')";
+
+ SqlCommand command = new SqlCommand(queryString, connection);
+ Int32 recordsAffected = command.ExecuteNonQuery();
+ //
+
+ //
+ // Assumes command is a valid SqlCommand with an open connection.
+ command.CommandText = "InsertCategory";
+ command.CommandType = CommandType.StoredProcedure;
+
+ SqlParameter parameter = command.Parameters.Add("@RowCount", SqlDbType.Int);
+ parameter.Direction = ParameterDirection.ReturnValue;
+
+ parameter = command.Parameters.Add("@CategoryName", SqlDbType.NChar, 15);
+
+ parameter = command.Parameters.Add("@Identity", SqlDbType.Int);
+ parameter.Direction = ParameterDirection.Output;
+
+ command.Parameters["@CategoryName"].Value = "New Category";
+ command.ExecuteNonQuery();
+
+ Int32 categoryID = (Int32) command.Parameters["@Identity"].Value;
+ Int32 rowCount = (Int32) command.Parameters["@RowCount"].Value;
+ //
+ }
+ }
+ }
+}
diff --git a/doc/samples/SqlCommand_ExecuteScalar_Return_Id.cs b/doc/samples/SqlCommand_ExecuteScalar_Return_Id.cs
new file mode 100644
index 0000000000..61f8029a16
--- /dev/null
+++ b/doc/samples/SqlCommand_ExecuteScalar_Return_Id.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Data;
+using Microsoft.Data.SqlClient;
+
+class Class1
+{
+ static void Main()
+ {
+ int ret = AddProductCategory("newval", GetConnectionString());
+ Console.WriteLine(ret.ToString());
+ Console.ReadLine();
+ }
+
+ //
+ static public int AddProductCategory(string newName, string connString)
+ {
+ Int32 newProdID = 0;
+ string sql =
+ "INSERT INTO Production.ProductCategory (Name) VALUES (@Name); "
+ + "SELECT CAST(scope_identity() AS int)";
+ using (SqlConnection conn = new SqlConnection(connString))
+ {
+ SqlCommand cmd = new SqlCommand(sql, conn);
+ cmd.Parameters.Add("@Name", SqlDbType.VarChar);
+ cmd.Parameters["@name"].Value = newName;
+ try
+ {
+ conn.Open();
+ newProdID = (Int32)cmd.ExecuteScalar();
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex.Message);
+ }
+ }
+ return (int)newProdID;
+ }
+
+ //
+ static private string GetConnectionString()
+ {
+ // To avoid storing the connection string in your code,
+ // you can retrieve it from a configuration file.
+ return "Data Source=(local);Initial Catalog=AdventureWorks;"
+ + "Integrated Security=true";
+ }
+}
diff --git a/doc/samples/SqlDataAdapter_FillDataSet.cs b/doc/samples/SqlDataAdapter_FillDataSet.cs
new file mode 100644
index 0000000000..20b4232b1c
--- /dev/null
+++ b/doc/samples/SqlDataAdapter_FillDataSet.cs
@@ -0,0 +1,74 @@
+using System;
+using Microsoft.Data.SqlClient;
+using System.Data;
+
+namespace NextResultCS
+{
+ class Program
+ {
+ static void Main()
+ {
+ string s = GetConnectionString();
+ SqlConnection c = new SqlConnection(s);
+ GetCustomers(c);
+ PrintCustomersOrders(c, c);
+ Console.ReadLine();
+ }
+
+ static DataSet GetCustomers(SqlConnection connection)
+ {
+ using (connection)
+ {
+ //
+ // Assumes that connection is a valid SqlConnection object.
+ string queryString =
+ "SELECT CustomerID, CompanyName FROM dbo.Customers";
+ SqlDataAdapter adapter = new SqlDataAdapter(queryString, connection);
+
+ DataSet customers = new DataSet();
+ adapter.Fill(customers, "Customers");
+ //
+ return customers;
+ }
+ }
+
+ static void PrintCustomersOrders(SqlConnection customerConnection, SqlConnection orderConnection)
+ {
+ using (customerConnection)
+ using (orderConnection)
+ {
+ //
+ // Assumes that customerConnection and orderConnection are valid SqlConnection objects.
+ SqlDataAdapter custAdapter = new SqlDataAdapter(
+ "SELECT * FROM dbo.Customers", customerConnection);
+ SqlDataAdapter ordAdapter = new SqlDataAdapter(
+ "SELECT * FROM Orders", orderConnection);
+
+ DataSet customerOrders = new DataSet();
+
+ custAdapter.Fill(customerOrders, "Customers");
+ ordAdapter.Fill(customerOrders, "Orders");
+
+ DataRelation relation = customerOrders.Relations.Add("CustOrders",
+ customerOrders.Tables["Customers"].Columns["CustomerID"],
+ customerOrders.Tables["Orders"].Columns["CustomerID"]);
+
+ foreach (DataRow pRow in customerOrders.Tables["Customers"].Rows)
+ {
+ Console.WriteLine(pRow["CustomerID"]);
+ foreach (DataRow cRow in pRow.GetChildRows(relation))
+ Console.WriteLine("\t" + cRow["OrderID"]);
+ }
+ //
+ }
+ }
+
+ static private string GetConnectionString()
+ {
+ // To avoid storing the connection string in your code,
+ // you can retrieve it from a configuration file.
+ return "Data Source=(local);Initial Catalog=Northwind;"
+ + "Integrated Security=SSPI";
+ }
+ }
+}
diff --git a/doc/samples/SqlDataAdapter_SqlDataAdapter.cs b/doc/samples/SqlDataAdapter_SqlDataAdapter.cs
index beb2486cbd..f48edacc8a 100644
--- a/doc/samples/SqlDataAdapter_SqlDataAdapter.cs
+++ b/doc/samples/SqlDataAdapter_SqlDataAdapter.cs
@@ -1,6 +1,5 @@
using System;
using System.Data;
-//
using Microsoft.Data.SqlClient;
class Program
@@ -8,8 +7,10 @@ class Program
static void Main()
{
}
+ //
public static SqlDataAdapter CreateSqlDataAdapter(SqlConnection connection)
{
+ // Assumes that connection is a valid SqlConnection object
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.MissingSchemaAction = MissingSchemaAction.AddWithKey;
@@ -45,5 +46,19 @@ public static SqlDataAdapter CreateSqlDataAdapter(SqlConnection connection)
return adapter;
}
+ //
+
+ public static SqlDataAdapter CustomerUpdateCommand(SqlDataAdapter adapter)
+ {
+ //
+ // Assumes that connection is a valid SqlAdapter object
+ adapter.UpdateCommand.Parameters.Add("@CompanyName",
+ SqlDbType.VarChar, 15, "CompanyName");
+ SqlParameter parameter = adapter.UpdateCommand.Parameters.Add("@CustomerID",
+ SqlDbType.Char, 5, "CustomerID");
+ parameter.SourceVersion = DataRowVersion.Original;
+ //
+ return adapter;
+ }
+
}
-//
diff --git a/doc/samples/SqlDataReader_GetSchemaTable.cs b/doc/samples/SqlDataReader_GetSchemaTable.cs
new file mode 100644
index 0000000000..5f540ae5d9
--- /dev/null
+++ b/doc/samples/SqlDataReader_GetSchemaTable.cs
@@ -0,0 +1,54 @@
+using System;
+using Microsoft.Data.SqlClient;
+using System.Data;
+
+namespace NextResultCS
+{
+ class Program
+ {
+ static void Main()
+ {
+ string s = GetConnectionString();
+ SqlConnection c = new SqlConnection(s);
+ GetSchemaInfo(c);
+ Console.ReadLine();
+ }
+ //
+ static void GetSchemaInfo(SqlConnection connection)
+ {
+ using (connection)
+ {
+ SqlCommand command = new SqlCommand(
+ "SELECT CategoryID, CategoryName FROM Categories;",
+ connection);
+ connection.Open();
+
+ SqlDataReader reader = command.ExecuteReader();
+
+ // Retrieve schema information about the current result-set.
+ DataTable schemaTable = reader.GetSchemaTable();
+
+ foreach (DataRow row in schemaTable.Rows)
+ {
+ foreach (DataColumn column in schemaTable.Columns)
+ {
+ Console.WriteLine(String.Format("{0} = {1}",
+ column.ColumnName, row[column]));
+ }
+ }
+
+ // Always call the Close method when you have finished using the DataReader object.
+ reader.Close();
+ }
+ }
+ //
+
+ static private string GetConnectionString()
+ {
+ // To avoid storing the connection string in your code,
+ // you can retrieve it from a configuration file.
+ return "Data Source=(local);Initial Catalog=Northwind;"
+ + "Integrated Security=SSPI";
+ }
+ }
+}
diff --git a/doc/samples/SqlDataReader_HasRows.cs b/doc/samples/SqlDataReader_HasRows.cs
new file mode 100644
index 0000000000..caeb01f1d6
--- /dev/null
+++ b/doc/samples/SqlDataReader_HasRows.cs
@@ -0,0 +1,57 @@
+using System;
+using Microsoft.Data.SqlClient;
+using System.Data;
+
+namespace NextResultCS
+{
+ class Program
+ {
+ static void Main()
+ {
+ string s = GetConnectionString();
+ SqlConnection c = new SqlConnection(s);
+ HasRows(c);
+ Console.ReadLine();
+ }
+
+ //
+ static void HasRows(SqlConnection connection)
+ {
+ using (connection)
+ {
+ SqlCommand command = new SqlCommand(
+ "SELECT CategoryID, CategoryName FROM Categories;",
+ connection);
+ connection.Open();
+
+ SqlDataReader reader = command.ExecuteReader();
+
+ // Check if the DataReader has any row.
+ if (reader.HasRows)
+ {
+ // Obtain a row from the query result.
+ while (reader.Read())
+ {
+ Console.WriteLine("{0}\t{1}", reader.GetInt32(0),
+ reader.GetString(1));
+ }
+ }
+ else
+ {
+ Console.WriteLine("No rows found.");
+ }
+ // Always call the Close method when you have finished using the DataReader object.
+ reader.Close();
+ }
+ }
+
+ //
+ static private string GetConnectionString()
+ {
+ // To avoid storing the connection string in your code,
+ // you can retrieve it from a configuration file.
+ return "Data Source=(local);Initial Catalog=Northwind;"
+ + "Integrated Security=SSPI";
+ }
+ }
+}
diff --git a/doc/samples/SqlDataReader_NextResult.cs b/doc/samples/SqlDataReader_NextResult.cs
new file mode 100644
index 0000000000..4dccf5a55f
--- /dev/null
+++ b/doc/samples/SqlDataReader_NextResult.cs
@@ -0,0 +1,62 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Microsoft.Data.SqlClient;
+using System.Data;
+
+namespace NextResultCS
+{
+ class Program
+ {
+ static void Main()
+ {
+ string s = GetConnectionString();
+ SqlConnection c = new SqlConnection(s);
+ RetrieveMultipleResults(c);
+ Console.ReadLine();
+ }
+
+ //
+ static void RetrieveMultipleResults(SqlConnection connection)
+ {
+ using (connection)
+ {
+ SqlCommand command = new SqlCommand(
+ "SELECT CategoryID, CategoryName FROM dbo.Categories;" +
+ "SELECT EmployeeID, LastName FROM dbo.Employees",
+ connection);
+ connection.Open();
+
+ SqlDataReader reader = command.ExecuteReader();
+
+ // Check if the DataReader has any row.
+ while (reader.HasRows)
+ {
+ Console.WriteLine("\t{0}\t{1}", reader.GetName(0),
+ reader.GetName(1));
+
+ // Obtain a row from the query result.
+ while (reader.Read())
+ {
+ Console.WriteLine("\t{0}\t{1}", reader.GetInt32(0),
+ reader.GetString(1));
+ }
+
+ // Hop to the next result-set.
+ reader.NextResult();
+ }
+ // Always call the Close method when you have finished using the DataReader object.
+ reader.Close();
+ }
+ }
+
+ //
+ static private string GetConnectionString()
+ {
+ // To avoid storing the connection string in your code,
+ // you can retrieve it from a configuration file.
+ return "Data Source=(local);Initial Catalog=Northwind;"
+ + "Integrated Security=SSPI";
+ }
+ }
+}
From bf5969db125e35f11230f9bafbe774a9a1eb7b5e Mon Sep 17 00:00:00 2001
From: Karina Zhou
Date: Wed, 25 Nov 2020 15:24:21 -0800
Subject: [PATCH 002/509] Add data classficiation with rank - docs code sample
(#817)
---
...taReader_DataDiscoveryAndClassification.cs | 67 +++++++++++++------
1 file changed, 48 insertions(+), 19 deletions(-)
diff --git a/doc/samples/SqlDataReader_DataDiscoveryAndClassification.cs b/doc/samples/SqlDataReader_DataDiscoveryAndClassification.cs
index d9dfcee124..352cb20fe9 100644
--- a/doc/samples/SqlDataReader_DataDiscoveryAndClassification.cs
+++ b/doc/samples/SqlDataReader_DataDiscoveryAndClassification.cs
@@ -24,8 +24,9 @@ public static void Main()
if (DataClassificationSupported(connection))
{
// Create the temporary table and retrieve its Data Discovery and Classification information.
- CreateTable(connection);
- RunTests(connection);
+ // Set rankEnabled to be true if testing with rank information.
+ CreateTable(connection, rankEnabled : true);
+ RunTests(connection, rankEnabled : true);
}
}
finally
@@ -65,7 +66,8 @@ public static bool DataClassificationSupported(SqlConnection connection)
/// Creates a temporary table for this sample program and sets tags for Sensitivity Classification.
///
/// The SqlConnection to work with.
- private static void CreateTable(SqlConnection connection)
+ /// True if rank information is enabled and false otherwise
+ private static void CreateTable(SqlConnection connection, bool rankEnabled = false)
{
SqlCommand command = new SqlCommand(null, connection);
@@ -81,35 +83,58 @@ private static void CreateTable(SqlConnection connection)
+ "[Fax] [nvarchar](30) MASKED WITH (FUNCTION = 'default()') NULL)";
command.ExecuteNonQuery();
- // Set Sensitivity Classification tags for table columns.
- command.CommandText = $"ADD SENSITIVITY CLASSIFICATION TO {tableName}"
- + ".CompanyName WITH (LABEL='PII', LABEL_ID='L1', INFORMATION_TYPE='Company Name', INFORMATION_TYPE_ID='COMPANY')";
- command.ExecuteNonQuery();
+ if (rankEnabled)
+ {
+ // Set Sensitivity Classification tags for table columns with rank information
+ command.CommandText = $"ADD SENSITIVITY CLASSIFICATION TO {tableName}"
+ + ".CompanyName WITH (LABEL='PII', LABEL_ID='L1', INFORMATION_TYPE='Company Name', INFORMATION_TYPE_ID='COMPANY', RANK=LOW)";
+ command.ExecuteNonQuery();
- command.CommandText = $"ADD SENSITIVITY CLASSIFICATION TO {tableName}"
- + ".ContactName WITH (LABEL='PII', LABEL_ID='L1', INFORMATION_TYPE='Person Name', INFORMATION_TYPE_ID='NAME')";
- command.ExecuteNonQuery();
+ command.CommandText = $"ADD SENSITIVITY CLASSIFICATION TO {tableName}"
+ + ".ContactName WITH (LABEL='PII', LABEL_ID='L1', INFORMATION_TYPE='Person Name', INFORMATION_TYPE_ID='NAME', RANK=LOW)";
+ command.ExecuteNonQuery();
- command.CommandText = $"ADD SENSITIVITY CLASSIFICATION TO {tableName}"
- + ".Phone WITH (LABEL='PII', LABEL_ID='L1', INFORMATION_TYPE='Contact Information', INFORMATION_TYPE_ID='CONTACT')";
- command.ExecuteNonQuery();
+ command.CommandText = $"ADD SENSITIVITY CLASSIFICATION TO {tableName}"
+ + ".Phone WITH (LABEL='PII', LABEL_ID='L1', INFORMATION_TYPE='Contact Information', INFORMATION_TYPE_ID='CONTACT', RANK=MEDIUM)";
+ command.ExecuteNonQuery();
- command.CommandText = $"ADD SENSITIVITY CLASSIFICATION TO {tableName}"
- + ".Fax WITH (LABEL='PII', LABEL_ID='L1', INFORMATION_TYPE='Contact Information', INFORMATION_TYPE_ID='CONTACT')";
- command.ExecuteNonQuery();
+ command.CommandText = $"ADD SENSITIVITY CLASSIFICATION TO {tableName}"
+ + ".Fax WITH (LABEL='PII', LABEL_ID='L1', INFORMATION_TYPE='Contact Information', INFORMATION_TYPE_ID='CONTACT', RANK=MEDIUM)";
+ command.ExecuteNonQuery();
+ }
+ else
+ {
+ // Set Sensitivity Classification tags for table columns without rank information
+ command.CommandText = $"ADD SENSITIVITY CLASSIFICATION TO {tableName}"
+ + ".CompanyName WITH (LABEL='PII', LABEL_ID='L1', INFORMATION_TYPE='Company Name', INFORMATION_TYPE_ID='COMPANY')";
+ command.ExecuteNonQuery();
+
+ command.CommandText = $"ADD SENSITIVITY CLASSIFICATION TO {tableName}"
+ + ".ContactName WITH (LABEL='PII', LABEL_ID='L1', INFORMATION_TYPE='Person Name', INFORMATION_TYPE_ID='NAME')";
+ command.ExecuteNonQuery();
+
+ command.CommandText = $"ADD SENSITIVITY CLASSIFICATION TO {tableName}"
+ + ".Phone WITH (LABEL='PII', LABEL_ID='L1', INFORMATION_TYPE='Contact Information', INFORMATION_TYPE_ID='CONTACT')";
+ command.ExecuteNonQuery();
+
+ command.CommandText = $"ADD SENSITIVITY CLASSIFICATION TO {tableName}"
+ + ".Fax WITH (LABEL='PII', LABEL_ID='L1', INFORMATION_TYPE='Contact Information', INFORMATION_TYPE_ID='CONTACT')";
+ command.ExecuteNonQuery();
+ }
}
///
/// Run query to fetch result set from target table.
///
/// The SqlConnection to work with.
- private static void RunTests(SqlConnection connection)
+ /// True if rank information is enabled and false otherwise
+ private static void RunTests(SqlConnection connection, bool rankEnabled = false)
{
SqlCommand command = new SqlCommand(null, connection);
command.CommandText = $"SELECT * FROM {tableName}";
using (SqlDataReader reader = command.ExecuteReader())
{
- PrintSensitivityClassification(reader);
+ PrintSensitivityClassification(reader, rankEnabled);
}
}
@@ -117,7 +142,8 @@ private static void RunTests(SqlConnection connection)
/// Prints Sensitivity Classification data as received in the result set.
///
/// The SqlDataReader to work with.
- private static void PrintSensitivityClassification(SqlDataReader reader)
+ /// True if rank information is enabled and false otherwise
+ private static void PrintSensitivityClassification(SqlDataReader reader, bool rankEnabled = false)
{
if (reader.SensitivityClassification != null)
{
@@ -140,8 +166,11 @@ private static void PrintSensitivityClassification(SqlDataReader reader)
Console.WriteLine($"Information Type: {sp.InformationType.Name}");
Console.WriteLine();
}
+
+ Console.WriteLine($"Sensitivity Rank: {sp.SensitivityRank.ToString()}");
}
}
+ Console.Writeline($"reader.SensitivityClassification.SensitivityRank : {reader.SensitivityClassification.SensitivityRank.ToString()}");
}
}
From 8ad8da6bc1f7314ec37b5fda1b4e991a878a6072 Mon Sep 17 00:00:00 2001
From: Karina Zhou
Date: Fri, 27 Nov 2020 10:46:28 -0800
Subject: [PATCH 003/509] Add more code samples for documentation - Transaction
and GetSchema (#824)
---
.../SqlConnection_GetSchema_Restriction.cs | 40 ++++++++
doc/samples/SqlConnection_GetSchema_Tables.cs | 36 +++++++
doc/samples/SqlDataAdapter_Concurrency.cs | 62 ++++++++++++
doc/samples/SqlTransactionLocal.cs | 57 +++++++++++
doc/samples/SqlTransactionScope.cs | 99 +++++++++++++++++++
5 files changed, 294 insertions(+)
create mode 100644 doc/samples/SqlConnection_GetSchema_Restriction.cs
create mode 100644 doc/samples/SqlConnection_GetSchema_Tables.cs
create mode 100644 doc/samples/SqlDataAdapter_Concurrency.cs
create mode 100644 doc/samples/SqlTransactionLocal.cs
create mode 100644 doc/samples/SqlTransactionScope.cs
diff --git a/doc/samples/SqlConnection_GetSchema_Restriction.cs b/doc/samples/SqlConnection_GetSchema_Restriction.cs
new file mode 100644
index 0000000000..209b0b8c3a
--- /dev/null
+++ b/doc/samples/SqlConnection_GetSchema_Restriction.cs
@@ -0,0 +1,40 @@
+//
+using System;
+using System.Data;
+using Microsoft.Data.SqlClient;
+
+class Program
+{
+ static void Main(string[] args)
+ {
+ string connectionString = "Data Source = localhost; Integrated Security = true; Initial Catalog = AdventureWorks";
+
+ using (SqlConnection connection = new SqlConnection(connectionString))
+ {
+ connection.Open();
+
+ // Specify the restrictions.
+ string[] restrictions = new string[4];
+ restrictions[1] = "Sales";
+ System.Data.DataTable table = connection.GetSchema("Tables", restrictions);
+
+ // Display the contents of the table.
+ DisplayData(table);
+ Console.WriteLine("Press any key to continue.");
+ Console.ReadKey();
+ }
+ }
+
+ private static void DisplayData(System.Data.DataTable table)
+ {
+ foreach (System.Data.DataRow row in table.Rows)
+ {
+ foreach (System.Data.DataColumn col in table.Columns)
+ {
+ Console.WriteLine("{0} = {1}", col.ColumnName, row[col]);
+ }
+ Console.WriteLine("============================");
+ }
+ }
+}
+//
diff --git a/doc/samples/SqlConnection_GetSchema_Tables.cs b/doc/samples/SqlConnection_GetSchema_Tables.cs
new file mode 100644
index 0000000000..34f04439a6
--- /dev/null
+++ b/doc/samples/SqlConnection_GetSchema_Tables.cs
@@ -0,0 +1,36 @@
+//
+using System;
+using System.Data;
+using Microsoft.Data.SqlClient;
+
+class Program
+{
+ static void Main(string[] args)
+ {
+ string connectionString = "Data Source = localhost; Integrated Security = true; Initial Catalog = AdventureWorks";
+
+ using (SqlConnection connection = new SqlConnection(connectionString))
+ {
+ connection.Open();
+ DataTable table = connection.GetSchema("Tables");
+
+ // Display the contents of the table.
+ DisplayData(table);
+ Console.WriteLine("Press any key to continue.");
+ Console.ReadKey();
+ }
+ }
+
+ private static void DisplayData(System.Data.DataTable table)
+ {
+ foreach (System.Data.DataRow row in table.Rows)
+ {
+ foreach (System.Data.DataColumn col in table.Columns)
+ {
+ Console.WriteLine("{0} = {1}", col.ColumnName, row[col]);
+ }
+ Console.WriteLine("============================");
+ }
+ }
+}
+//
diff --git a/doc/samples/SqlDataAdapter_Concurrency.cs b/doc/samples/SqlDataAdapter_Concurrency.cs
new file mode 100644
index 0000000000..fd40eb9f7f
--- /dev/null
+++ b/doc/samples/SqlDataAdapter_Concurrency.cs
@@ -0,0 +1,62 @@
+//
+using System;
+using System.Data;
+using Microsoft.Data.SqlClient;
+
+class Program
+{
+ static void Main(string[] args)
+ {
+ string connectionString = "Data Source = localhost; Integrated Security = true; Initial Catalog = Northwind";
+
+ using (SqlConnection connection = new SqlConnection(connectionString))
+ {
+ // Assumes connection is a valid SqlConnection.
+ SqlDataAdapter adapter = new SqlDataAdapter(
+ "SELECT CustomerID, CompanyName FROM Customers ORDER BY CustomerID",
+ connection);
+
+ // The Update command checks for optimistic concurrency violations
+ // in the WHERE clause.
+ adapter.UpdateCommand = new SqlCommand("UPDATE Customers Set CustomerID = @CustomerID, CompanyName = @CompanyName " +
+ "WHERE CustomerID = @oldCustomerID AND CompanyName = @oldCompanyName", connection);
+ adapter.UpdateCommand.Parameters.Add(
+ "@CustomerID", SqlDbType.NChar, 5, "CustomerID");
+ adapter.UpdateCommand.Parameters.Add(
+ "@CompanyName", SqlDbType.NVarChar, 30, "CompanyName");
+
+ // Pass the original values to the WHERE clause parameters.
+ SqlParameter parameter = adapter.UpdateCommand.Parameters.Add(
+ "@oldCustomerID", SqlDbType.NChar, 5, "CustomerID");
+ parameter.SourceVersion = DataRowVersion.Original;
+ parameter = adapter.UpdateCommand.Parameters.Add(
+ "@oldCompanyName", SqlDbType.NVarChar, 30, "CompanyName");
+ parameter.SourceVersion = DataRowVersion.Original;
+
+ // Add the RowUpdated event handler.
+ adapter.RowUpdated += new SqlRowUpdatedEventHandler(OnRowUpdated);
+
+ DataSet dataSet = new DataSet();
+ adapter.Fill(dataSet, "Customers");
+
+ // Modify the DataSet contents.
+ adapter.Update(dataSet, "Customers");
+
+ foreach (DataRow dataRow in dataSet.Tables["Customers"].Rows)
+ {
+ if (dataRow.HasErrors)
+ Console.WriteLine(dataRow[0] + "\n" + dataRow.RowError);
+ }
+ }
+ }
+
+ protected static void OnRowUpdated(object sender, SqlRowUpdatedEventArgs args)
+ {
+ if (args.RecordsAffected == 0)
+ {
+ args.Row.RowError = "Optimistic Concurrency Violation Encountered";
+ args.Status = UpdateStatus.SkipCurrentRow;
+ }
+ }
+}
+//
diff --git a/doc/samples/SqlTransactionLocal.cs b/doc/samples/SqlTransactionLocal.cs
new file mode 100644
index 0000000000..29d29526ab
--- /dev/null
+++ b/doc/samples/SqlTransactionLocal.cs
@@ -0,0 +1,57 @@
+//
+using System;
+using Microsoft.Data.SqlClient;
+
+class Program
+{
+ static void Main(string[] args)
+ {
+ string connectionString = "Data Source = localhost; Integrated Security = true; Initial Catalog = AdventureWorks";
+
+ using (SqlConnection connection = new SqlConnection(connectionString))
+ {
+ connection.Open();
+
+ // Start a local transaction.
+ SqlTransaction sqlTran = connection.BeginTransaction();
+
+ // Enlist a command in the current transaction.
+ SqlCommand command = connection.CreateCommand();
+ command.Transaction = sqlTran;
+
+ try
+ {
+ // Execute two separate commands.
+ command.CommandText =
+ "INSERT INTO Production.ScrapReason(Name) VALUES('Wrong size')";
+ command.ExecuteNonQuery();
+ command.CommandText =
+ "INSERT INTO Production.ScrapReason(Name) VALUES('Wrong color')";
+ command.ExecuteNonQuery();
+
+ // Commit the transaction.
+ sqlTran.Commit();
+ Console.WriteLine("Both records were written to database.");
+ }
+ catch (Exception ex)
+ {
+ // Handle the exception if the transaction fails to commit.
+ Console.WriteLine(ex.Message);
+
+ try
+ {
+ // Attempt to roll back the transaction.
+ sqlTran.Rollback();
+ }
+ catch (Exception exRollback)
+ {
+ // Throws an InvalidOperationException if the connection
+ // is closed or the transaction has already been rolled
+ // back on the server.
+ Console.WriteLine(exRollback.Message);
+ }
+ }
+ }
+ }
+}
+//
diff --git a/doc/samples/SqlTransactionScope.cs b/doc/samples/SqlTransactionScope.cs
new file mode 100644
index 0000000000..77f5d75694
--- /dev/null
+++ b/doc/samples/SqlTransactionScope.cs
@@ -0,0 +1,99 @@
+//
+using System;
+using System.Transactions;
+using Microsoft.Data.SqlClient;
+
+class Program
+{
+ static void Main(string[] args)
+ {
+ string connectionString = "Data Source = localhost; Integrated Security = true; Initial Catalog = AdventureWorks";
+
+ string commandText1 = "INSERT INTO Production.ScrapReason(Name) VALUES('Wrong size')";
+ string commandText2 = "INSERT INTO Production.ScrapReason(Name) VALUES('Wrong color')";
+
+ int result = CreateTransactionScope(connectionString, connectionString, commandText1, commandText2);
+
+ Console.WriteLine("result = " + result);
+ }
+
+ static public int CreateTransactionScope(string connectString1, string connectString2,
+ string commandText1, string commandText2)
+ {
+ // Initialize the return value to zero and create a StringWriter to display results.
+ int returnValue = 0;
+ System.IO.StringWriter writer = new System.IO.StringWriter();
+
+ // Create the TransactionScope in which to execute the commands, guaranteeing
+ // that both commands will commit or roll back as a single unit of work.
+ using (TransactionScope scope = new TransactionScope())
+ {
+ using (SqlConnection connection1 = new SqlConnection(connectString1))
+ {
+ try
+ {
+ // Opening the connection automatically enlists it in the
+ // TransactionScope as a lightweight transaction.
+ connection1.Open();
+
+ // Create the SqlCommand object and execute the first command.
+ SqlCommand command1 = new SqlCommand(commandText1, connection1);
+ returnValue = command1.ExecuteNonQuery();
+ writer.WriteLine("Rows to be affected by command1: {0}", returnValue);
+
+ // if you get here, this means that command1 succeeded. By nesting
+ // the using block for connection2 inside that of connection1, you
+ // conserve server and network resources by opening connection2
+ // only when there is a chance that the transaction can commit.
+ using (SqlConnection connection2 = new SqlConnection(connectString2))
+ try
+ {
+ // The transaction is promoted to a full distributed
+ // transaction when connection2 is opened.
+ connection2.Open();
+
+ // Execute the second command in the second database.
+ returnValue = 0;
+ SqlCommand command2 = new SqlCommand(commandText2, connection2);
+ returnValue = command2.ExecuteNonQuery();
+ writer.WriteLine("Rows to be affected by command2: {0}", returnValue);
+ }
+ catch (Exception ex)
+ {
+ // Display information that command2 failed.
+ writer.WriteLine("returnValue for command2: {0}", returnValue);
+ writer.WriteLine("Exception Message2: {0}", ex.Message);
+ }
+ }
+ catch (Exception ex)
+ {
+ // Display information that command1 failed.
+ writer.WriteLine("returnValue for command1: {0}", returnValue);
+ writer.WriteLine("Exception Message1: {0}", ex.Message);
+ }
+ }
+
+ // If an exception has been thrown, Complete will not
+ // be called and the transaction is rolled back.
+ scope.Complete();
+ }
+
+ // The returnValue is greater than 0 if the transaction committed.
+ if (returnValue > 0)
+ {
+ writer.WriteLine("Transaction was committed.");
+ }
+ else
+ {
+ // You could write additional business logic here, notify the caller by
+ // throwing a TransactionAbortedException, or log the failure.
+ writer.WriteLine("Transaction rolled back.");
+ }
+
+ // Display messages.
+ Console.WriteLine(writer.ToString());
+
+ return returnValue;
+ }
+}
+//
From 6db9cc695a01d26800ecbdc36e5e10ff2ffe12f9 Mon Sep 17 00:00:00 2001
From: Cheena Malhotra
Date: Mon, 30 Nov 2020 17:08:24 -0800
Subject: [PATCH 004/509] Add support for .NET Standard 2.0 in AKV provider
(#823)
---
build.proj | 13 +++++++++++++
...lwaysEncrypted.AzureKeyVaultProvider.csproj | 2 +-
.../add-ons/Directory.Build.props | 1 +
...lwaysEncrypted.AzureKeyVaultProvider.nuspec | 18 ++++++++++++++++++
4 files changed, 33 insertions(+), 1 deletion(-)
diff --git a/build.proj b/build.proj
index 2dcc4ae354..40429e8481 100644
--- a/build.proj
+++ b/build.proj
@@ -125,6 +125,12 @@
+
+
+
+
+
+
@@ -132,4 +138,11 @@
+
+
+
+
+
+
+
diff --git a/src/Microsoft.Data.SqlClient/add-ons/AzureKeyVaultProvider/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.csproj b/src/Microsoft.Data.SqlClient/add-ons/AzureKeyVaultProvider/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.csproj
index b882eb77b7..8a2993b3f5 100644
--- a/src/Microsoft.Data.SqlClient/add-ons/AzureKeyVaultProvider/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.csproj
+++ b/src/Microsoft.Data.SqlClient/add-ons/AzureKeyVaultProvider/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.csproj
@@ -4,7 +4,7 @@
Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProviderAzureKeyVaultProvider{9073ABEF-92E0-4702-BB23-2C99CEF9BDD7}
- netcoreapp
+ netcoreappnetfxDebug;Release;net46-Release;net46-Debug;netcoreapp2.1-Debug;netcoreapp2.1-Release;netcoreapp3.1-Debug;netcoreapp3.1-ReleaseAnyCPU;x86;x64
diff --git a/src/Microsoft.Data.SqlClient/add-ons/Directory.Build.props b/src/Microsoft.Data.SqlClient/add-ons/Directory.Build.props
index a76d932f17..a70373e4cf 100644
--- a/src/Microsoft.Data.SqlClient/add-ons/Directory.Build.props
+++ b/src/Microsoft.Data.SqlClient/add-ons/Directory.Build.props
@@ -28,6 +28,7 @@
+ netstandard2.0netcoreapp2.1netcoreapp3.1net46
diff --git a/tools/specs/add-ons/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.nuspec b/tools/specs/add-ons/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.nuspec
index 62365bd9da..7ed107896b 100644
--- a/tools/specs/add-ons/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.nuspec
+++ b/tools/specs/add-ons/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.nuspec
@@ -38,6 +38,13 @@ Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyStoreProvider.SqlColumnEncrypti
+
+
+
+
+
+
+
@@ -64,5 +71,16 @@ Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyStoreProvider.SqlColumnEncrypti
+
+
+
+
+
+
+
+
+
+
+
From 5066537bb44c8794bade9f8473fd1d465aa3ecdc Mon Sep 17 00:00:00 2001
From: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com>
Date: Mon, 30 Nov 2020 17:15:45 -0800
Subject: [PATCH 005/509] Add samples (#830)
Related to the next part of porting documents from .NET Framework documents.
---
doc/samples/SqlDataAdapter_Batch.cs | 69 +++++++
doc/samples/SqlDataAdapter_Events.cs | 95 +++++++++
doc/samples/SqlDataAdapter_FillDataSet.cs | 42 +++-
doc/samples/SqlDataAdapter_Paging.cs | 91 +++++++++
doc/samples/SqlDataAdapter_Properties.cs | 206 ++++++++++++++++++++
doc/samples/SqlDataAdapter_TableMappings.cs | 98 ++++++++++
doc/samples/SqlDataAdapter_Update.cs | 79 ++++++++
7 files changed, 679 insertions(+), 1 deletion(-)
create mode 100644 doc/samples/SqlDataAdapter_Batch.cs
create mode 100644 doc/samples/SqlDataAdapter_Events.cs
create mode 100644 doc/samples/SqlDataAdapter_Paging.cs
create mode 100644 doc/samples/SqlDataAdapter_Properties.cs
create mode 100644 doc/samples/SqlDataAdapter_TableMappings.cs
create mode 100644 doc/samples/SqlDataAdapter_Update.cs
diff --git a/doc/samples/SqlDataAdapter_Batch.cs b/doc/samples/SqlDataAdapter_Batch.cs
new file mode 100644
index 0000000000..f7deb7e87d
--- /dev/null
+++ b/doc/samples/SqlDataAdapter_Batch.cs
@@ -0,0 +1,69 @@
+using System;
+using Microsoft.Data.SqlClient;
+using System.Data;
+
+namespace DataAdapterTest
+{
+ class Program
+ {
+ static void Main()
+ {
+ }
+
+ //
+ public static void BatchUpdate(DataTable dataTable, Int32 batchSize)
+ {
+ // Assumes GetConnectionString() returns a valid connection string.
+ string connectionString = GetConnectionString();
+
+ // Connect to the AdventureWorks database.
+ using (SqlConnection connection = new SqlConnection(connectionString))
+ {
+ // Create a SqlDataAdapter.
+ SqlDataAdapter adapter = new SqlDataAdapter();
+
+ // Set the UPDATE command and parameters.
+ adapter.UpdateCommand = new SqlCommand(
+ "UPDATE Production.ProductCategory SET "
+ + "Name=@Name WHERE ProductCategoryID=@ProdCatID;",
+ connection);
+ adapter.UpdateCommand.Parameters.Add("@Name",
+ SqlDbType.NVarChar, 50, "Name");
+ adapter.UpdateCommand.Parameters.Add("@ProdCatID",
+ SqlDbType.Int, 4, "ProductCategoryID");
+ adapter.UpdateCommand.UpdatedRowSource = UpdateRowSource.None;
+
+ // Set the INSERT command and parameter.
+ adapter.InsertCommand = new SqlCommand(
+ "INSERT INTO Production.ProductCategory (Name) VALUES (@Name);",
+ connection);
+ adapter.InsertCommand.Parameters.Add("@Name",
+ SqlDbType.NVarChar, 50, "Name");
+ adapter.InsertCommand.UpdatedRowSource = UpdateRowSource.None;
+
+ // Set the DELETE command and parameter.
+ adapter.DeleteCommand = new SqlCommand(
+ "DELETE FROM Production.ProductCategory "
+ + "WHERE ProductCategoryID=@ProdCatID;", connection);
+ adapter.DeleteCommand.Parameters.Add("@ProdCatID",
+ SqlDbType.Int, 4, "ProductCategoryID");
+ adapter.DeleteCommand.UpdatedRowSource = UpdateRowSource.None;
+
+ // Set the batch size.
+ adapter.UpdateBatchSize = batchSize;
+
+ // Execute the update.
+ adapter.Update(dataTable);
+ }
+ }
+ //
+
+ static private string GetConnectionString()
+ {
+ // To avoid storing the connection string in your code,
+ // you can retrieve it from a configuration file.
+ return "Data Source=(local);Initial Catalog=AdventureWorks;"
+ + "Integrated Security=SSPI";
+ }
+ }
+}
diff --git a/doc/samples/SqlDataAdapter_Events.cs b/doc/samples/SqlDataAdapter_Events.cs
new file mode 100644
index 0000000000..deacdeb298
--- /dev/null
+++ b/doc/samples/SqlDataAdapter_Events.cs
@@ -0,0 +1,95 @@
+using System;
+using Microsoft.Data.SqlClient;
+using System.Data;
+
+namespace DataAdapterTest
+{
+ class Program
+ {
+ static void Main()
+ {
+ }
+
+ //
+ static DataSet DataAdapterEventsDemo(SqlConnection connection, DataSet custDS)
+ {
+ // Assumes that connection is a valid SqlConnection object
+ // and custDS includes the Customers table.
+ SqlDataAdapter custAdapter = new SqlDataAdapter(
+ "SELECT CustomerID, CompanyName FROM Customers", connection);
+
+ // Add handlers.
+ custAdapter.RowUpdating += new SqlRowUpdatingEventHandler(OnRowUpdating);
+ custAdapter.RowUpdated += new SqlRowUpdatedEventHandler(OnRowUpdated);
+
+ // Set DataAdapter command properties, fill DataSet, modify DataSet.
+ custAdapter.Update(custDS, "Customers");
+
+ // Remove handlers.
+ custAdapter.RowUpdating -= new SqlRowUpdatingEventHandler(OnRowUpdating);
+ custAdapter.RowUpdated -= new SqlRowUpdatedEventHandler(OnRowUpdated);
+
+ return custDS;
+ }
+
+ protected static void OnRowUpdating(object sender, SqlRowUpdatingEventArgs args)
+ {
+ if (args.StatementType == StatementType.Delete)
+ {
+ // Saves the removing rows with additional information in a file.
+ System.IO.TextWriter tw = System.IO.File.AppendText("Deletes.log");
+ tw.WriteLine(
+ "{0}: Customer {1} Deleted.", DateTime.Now,
+ args.Row["CustomerID", DataRowVersion.Original]);
+ tw.Close();
+ }
+ }
+
+ protected static void OnRowUpdated(object sender, SqlRowUpdatedEventArgs args)
+ {
+ if (args.Status == UpdateStatus.ErrorsOccurred)
+ {
+ // Adds the error message to the row and skips from it.
+ args.Row.RowError = args.Errors.Message;
+ args.Status = UpdateStatus.SkipCurrentRow;
+ }
+ }
+ //
+
+ //
+ static DataSet DataAdapterFillAndError(SqlDataAdapter adapter)
+ {
+ // Assuemes adapter is a valid SqlDataAdapter object.
+ adapter.FillError += new FillErrorEventHandler(FillError);
+
+ DataSet dataSet = new DataSet();
+ adapter.Fill(dataSet);
+ return dataSet;
+ }
+
+ protected static void FillError(object sender, FillErrorEventArgs args)
+ {
+ if (args.Errors.GetType() == typeof(System.OverflowException))
+ {
+ // Code to handle precision loss.
+ // Add a row to table using the values from the first two columns.
+ DataRow myRow = args.DataTable.Rows.Add(new object[]
+ {args.Values[0], args.Values[1], DBNull.Value});
+ //Set the RowError containing the value for the third column.
+ myRow.RowError =
+ "OverflowException Encountered. Value from data source: " +
+ args.Values[2];
+ args.Continue = true;
+ }
+ }
+ //
+
+ static private string GetConnectionString()
+ {
+ // To avoid storing the connection string in your code,
+ // you can retrieve it from a configuration file.
+ return "Data Source=(local);Initial Catalog=Northwind;"
+ + "Integrated Security=SSPI";
+ }
+ }
+}
diff --git a/doc/samples/SqlDataAdapter_FillDataSet.cs b/doc/samples/SqlDataAdapter_FillDataSet.cs
index 20b4232b1c..0365bedc40 100644
--- a/doc/samples/SqlDataAdapter_FillDataSet.cs
+++ b/doc/samples/SqlDataAdapter_FillDataSet.cs
@@ -2,7 +2,7 @@
using Microsoft.Data.SqlClient;
using System.Data;
-namespace NextResultCS
+namespace DataAdapterTest
{
class Program
{
@@ -12,6 +12,8 @@ static void Main()
SqlConnection c = new SqlConnection(s);
GetCustomers(c);
PrintCustomersOrders(c, c);
+ CustomerFillSchema1(c);
+ CustomerFillSchema2(c);
Console.ReadLine();
}
@@ -63,6 +65,44 @@ static void PrintCustomersOrders(SqlConnection customerConnection, SqlConnection
}
}
+ static DataSet CustomerFillSchema1(SqlConnection connection)
+ {
+ using (connection)
+ {
+ //
+ // Assumes that connection is a valid SqlConnection object.
+ DataSet custDataSet = new DataSet();
+
+ SqlDataAdapter custAdapter = new SqlDataAdapter(
+ "SELECT * FROM dbo.Customers", connection);
+
+ custAdapter.FillSchema(custDataSet, SchemaType.Source, "Customers");
+ custAdapter.Fill(custDataSet, "Customers");
+ //
+
+ return custDataSet;
+ }
+ }
+
+ static DataSet CustomerFillSchema2(SqlConnection connection)
+ {
+ using (connection)
+ {
+ //
+ // Assumes that connection is a valid SqlConnection object.
+ DataSet custDataSet = new DataSet();
+
+ SqlDataAdapter custAdapter = new SqlDataAdapter(
+ "SELECT * FROM dbo.Customers", connection);
+
+ custAdapter.MissingSchemaAction = MissingSchemaAction.AddWithKey;
+ custAdapter.Fill(custDataSet, "Customers");
+ //
+
+ return custDataSet;
+ }
+ }
+
static private string GetConnectionString()
{
// To avoid storing the connection string in your code,
diff --git a/doc/samples/SqlDataAdapter_Paging.cs b/doc/samples/SqlDataAdapter_Paging.cs
new file mode 100644
index 0000000000..511c05ba16
--- /dev/null
+++ b/doc/samples/SqlDataAdapter_Paging.cs
@@ -0,0 +1,91 @@
+using System;
+using Microsoft.Data.SqlClient;
+using System.Data;
+
+namespace DataAdapterTest
+{
+ class Program
+ {
+ static void Main()
+ {
+ string s = GetConnectionString();
+ SqlConnection c = new SqlConnection(s);
+ GetOrders_Fill(c);
+ GetOrders_Select(c);
+ Console.ReadLine();
+ }
+
+ static DataSet GetOrders_Fill(SqlConnection connection)
+ {
+ using (connection)
+ {
+ //
+ int currentIndex = 0;
+ int pageSize = 5;
+
+ string orderSQL = "SELECT * FROM Orders ORDER BY OrderID";
+ // Assumes that connection is a valid SqlConnection object.
+ SqlDataAdapter adapter = new SqlDataAdapter(orderSQL, connection);
+
+ DataSet dataSet = new DataSet();
+ adapter.Fill(dataSet, currentIndex, pageSize, "Orders");
+ //
+
+ // Retrieve the next page.
+ //
+ currentIndex += pageSize;
+
+ // Assumes that dataset and adapter are valid objects.
+ dataSet.Tables["Orders"].Rows.Clear();
+ adapter.Fill(dataSet, currentIndex, pageSize, "Orders");
+ //
+
+ return dataSet;
+ }
+ }
+
+ static DataSet GetOrders_Select(SqlConnection connection)
+ {
+ using (connection)
+ {
+ //
+ int pageSize = 5;
+
+ string orderSQL = "SELECT TOP " + pageSize +
+ " * FROM Orders ORDER BY OrderID";
+
+ // Assumes that connection is a valid SqlConnection object.
+ SqlDataAdapter adapter = new SqlDataAdapter(orderSQL, connection);
+
+ DataSet dataSet = new DataSet();
+ adapter.Fill(dataSet, "Orders");
+ //
+
+ //
+ string lastRecord =
+ dataSet.Tables["Orders"].Rows[pageSize - 1]["OrderID"].ToString();
+ //
+
+ //
+ orderSQL = "SELECT TOP " + pageSize +
+ " * FROM Orders WHERE OrderID > " + lastRecord + " ORDER BY OrderID";
+ adapter.SelectCommand.CommandText = orderSQL;
+
+ dataSet.Tables["Orders"].Rows.Clear();
+
+ adapter.Fill(dataSet, "Orders");
+ //
+
+ return dataSet;
+ }
+ }
+
+ static private string GetConnectionString()
+ {
+ // To avoid storing the connection string in your code,
+ // you can retrieve it from a configuration file.
+ return "Data Source=(local);Initial Catalog=Northwind;"
+ + "Integrated Security=SSPI";
+ }
+ }
+}
diff --git a/doc/samples/SqlDataAdapter_Properties.cs b/doc/samples/SqlDataAdapter_Properties.cs
new file mode 100644
index 0000000000..d66385c5d8
--- /dev/null
+++ b/doc/samples/SqlDataAdapter_Properties.cs
@@ -0,0 +1,206 @@
+//
+using System;
+using System.Data;
+using System.Data.Common;
+using Microsoft.Data.SqlClient;
+using System.Linq;
+using CSDataAdapterOperations.Properties;
+
+class Program
+{
+ static void Main(string[] args)
+ {
+ Settings settings = new Settings();
+
+ // Copy the data from the database. Get the table Department and Course from the database.
+ String selectString = @"SELECT [DepartmentID],[Name],[Budget],[StartDate],[Administrator]
+ FROM [MySchool].[dbo].[Department];
+
+ SELECT [CourseID],@Year as [Year],Max([Title]) as [Title],
+ Max([Credits]) as [Credits],Max([DepartmentID]) as [DepartmentID]
+ FROM [MySchool].[dbo].[Course]
+ Group by [CourseID]";
+
+ DataSet mySchool = new DataSet();
+
+ SqlCommand selectCommand = new SqlCommand(selectString);
+ SqlParameter parameter = selectCommand.Parameters.Add("@Year", SqlDbType.SmallInt, 2);
+ parameter.Value = new Random(DateTime.Now.Millisecond).Next(9999);
+
+ // Use DataTableMapping to map the source tables and the destination tables.
+ DataTableMapping[] tableMappings = { new DataTableMapping("Table", "Department"), new DataTableMapping("Table1", "Course") };
+ CopyData(mySchool, settings.MySchoolConnectionString, selectCommand, tableMappings);
+
+ Console.WriteLine("The following tables are from the database.");
+ foreach (DataTable table in mySchool.Tables)
+ {
+ Console.WriteLine(table.TableName);
+ ShowDataTable(table);
+ }
+
+ // Roll back the changes
+ DataTable department = mySchool.Tables["Department"];
+ DataTable course = mySchool.Tables["Course"];
+
+ department.Rows[0]["Name"] = "New" + department.Rows[0][1];
+ course.Rows[0]["Title"] = "New" + course.Rows[0]["Title"];
+ course.Rows[0]["Credits"] = 10;
+
+ Console.WriteLine("After we changed the tables:");
+ foreach (DataTable table in mySchool.Tables)
+ {
+ Console.WriteLine(table.TableName);
+ ShowDataTable(table);
+ }
+
+ department.RejectChanges();
+ Console.WriteLine("After use the RejectChanges method in Department table to roll back the changes:");
+ ShowDataTable(department);
+
+ DataColumn[] primaryColumns = { course.Columns["CourseID"] };
+ DataColumn[] resetColumns = { course.Columns["Title"] };
+ ResetCourse(course, settings.MySchoolConnectionString, primaryColumns, resetColumns);
+ Console.WriteLine("After use the ResetCourse method in Course table to roll back the changes:");
+ ShowDataTable(course);
+
+ // Batch update the table.
+ String insertString = @"Insert into [MySchool].[dbo].[Course]([CourseID],[Year],[Title],
+ [Credits],[DepartmentID])
+ values (@CourseID,@Year,@Title,@Credits,@DepartmentID)";
+ SqlCommand insertCommand = new SqlCommand(insertString);
+ insertCommand.Parameters.Add("@CourseID", SqlDbType.NVarChar, 10, "CourseID");
+ insertCommand.Parameters.Add("@Year", SqlDbType.SmallInt, 2, "Year");
+ insertCommand.Parameters.Add("@Title", SqlDbType.NVarChar, 100, "Title");
+ insertCommand.Parameters.Add("@Credits", SqlDbType.Int, 4, "Credits");
+ insertCommand.Parameters.Add("@DepartmentID", SqlDbType.Int, 4, "DepartmentID");
+
+ const Int32 batchSize = 10;
+ BatchInsertUpdate(course, settings.MySchoolConnectionString, insertCommand, batchSize);
+ }
+
+ private static void CopyData(DataSet dataSet, String connectionString, SqlCommand selectCommand, DataTableMapping[] tableMappings)
+ {
+ using (SqlConnection connection = new SqlConnection(connectionString))
+ {
+ selectCommand.Connection = connection;
+
+ connection.Open();
+
+ using (SqlDataAdapter adapter = new SqlDataAdapter(selectCommand))
+ {
+ adapter.TableMappings.AddRange(tableMappings);
+ // If set the AcceptChangesDuringFill as the false, AcceptChanges will not be called on a
+ // DataRow after it is added to the DataTable during any of the Fill operations.
+ adapter.AcceptChangesDuringFill = false;
+
+ adapter.Fill(dataSet);
+ }
+ }
+ }
+
+ // Roll back only one column or several columns data of the Course table by call ResetDataTable method.
+ private static void ResetCourse(DataTable table, String connectionString,
+ DataColumn[] primaryColumns, DataColumn[] resetColumns)
+ {
+ table.PrimaryKey = primaryColumns;
+
+ // Build the query string
+ String primaryCols = String.Join(",", primaryColumns.Select(col => col.ColumnName));
+ String resetCols = String.Join(",", resetColumns.Select(col => $"Max({col.ColumnName}) as {col.ColumnName}"));
+
+ String selectString = $"Select {primaryCols},{resetCols} from Course Group by {primaryCols}";
+
+ SqlCommand selectCommand = new SqlCommand(selectString);
+
+ ResetDataTable(table, connectionString, selectCommand);
+ }
+
+ // RejectChanges will roll back all changes made to the table since it was loaded, or the last time AcceptChanges
+ // was called. When you copy from the database, you can lose all the data after calling RejectChanges
+ // The ResetDataTable method rolls back one or more columns of data.
+ private static void ResetDataTable(DataTable table, String connectionString,
+ SqlCommand selectCommand)
+ {
+ using (SqlConnection connection = new SqlConnection(connectionString))
+ {
+ selectCommand.Connection = connection;
+
+ connection.Open();
+
+ using (SqlDataAdapter adapter = new SqlDataAdapter(selectCommand))
+ {
+ // The incoming values for this row will be written to the current version of each
+ // column. The original version of each column's data will not be changed.
+ adapter.FillLoadOption = LoadOption.Upsert;
+
+ adapter.Fill(table);
+ }
+ }
+ }
+
+ private static void BatchInsertUpdate(DataTable table, String connectionString,
+ SqlCommand insertCommand, Int32 batchSize)
+ {
+ using (SqlConnection connection = new SqlConnection(connectionString))
+ {
+ insertCommand.Connection = connection;
+ // When setting UpdateBatchSize to a value other than 1, all the commands
+ // associated with the SqlDataAdapter have to have their UpdatedRowSource
+ // property set to None or OutputParameters. An exception is thrown otherwise.
+ insertCommand.UpdatedRowSource = UpdateRowSource.None;
+
+ connection.Open();
+
+ using (SqlDataAdapter adapter = new SqlDataAdapter())
+ {
+ adapter.InsertCommand = insertCommand;
+ // Gets or sets the number of rows that are processed in each round-trip to the server.
+ // Setting it to 1 disables batch updates, as rows are sent one at a time.
+ adapter.UpdateBatchSize = batchSize;
+
+ adapter.Update(table);
+
+ Console.WriteLine("Successfully to update the table.");
+ }
+ }
+ }
+
+ private static void ShowDataTable(DataTable table)
+ {
+ foreach (DataColumn col in table.Columns)
+ {
+ Console.Write("{0,-14}", col.ColumnName);
+ }
+ Console.WriteLine("{0,-14}", "RowState");
+
+ foreach (DataRow row in table.Rows)
+ {
+ foreach (DataColumn col in table.Columns)
+ {
+ if (col.DataType.Equals(typeof(DateTime)))
+ Console.Write("{0,-14:d}", row[col]);
+ else if (col.DataType.Equals(typeof(Decimal)))
+ Console.Write("{0,-14:C}", row[col]);
+ else
+ Console.Write("{0,-14}", row[col]);
+ }
+ Console.WriteLine("{0,-14}", row.RowState);
+ }
+ }
+}
+
+namespace CSDataAdapterOperations.Properties
+{
+ internal sealed partial class Settings : System.Configuration.ApplicationSettingsBase
+ {
+ private static readonly Settings defaultInstance =
+ ((Settings)(System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default => defaultInstance;
+
+ [System.Configuration.ApplicationScopedSetting()]
+ [System.Configuration.DefaultSettingValue("Data Source=(local);Initial Catalog=MySchool;Integrated Security=True")]
+ public string MySchoolConnectionString => ((string)(this["MySchoolConnectionString"]));
+ }
+}
+//
diff --git a/doc/samples/SqlDataAdapter_TableMappings.cs b/doc/samples/SqlDataAdapter_TableMappings.cs
new file mode 100644
index 0000000000..4f2fc112e3
--- /dev/null
+++ b/doc/samples/SqlDataAdapter_TableMappings.cs
@@ -0,0 +1,98 @@
+using System;
+using Microsoft.Data.SqlClient;
+using System.Data;
+using System.Data.Common;
+
+namespace DataAdapterTest
+{
+ class Program
+ {
+ static void Main()
+ {
+ string s = GetConnectionString();
+ SqlConnection c = new SqlConnection(s);
+ CustomerTableMapping(c);
+ BizTableMapping(c);
+ GetCustomersOrders(c);
+ Console.ReadLine();
+ }
+
+ static DataSet CustomerTableMapping(SqlConnection connection)
+ {
+ using (connection)
+ {
+ //
+ // Assumes that connection is a valid SqlConnection object.
+ DataSet custDataSet = new DataSet();
+
+ SqlDataAdapter custAdapter = new SqlDataAdapter(
+ "SELECT * FROM dbo.Customers", connection);
+
+ DataTableMapping mapping =
+ custAdapter.TableMappings.Add("Table", "NorthwindCustomers");
+ mapping.ColumnMappings.Add("CompanyName", "Company");
+ mapping.ColumnMappings.Add("ContactName", "Contact");
+ mapping.ColumnMappings.Add("PostalCode", "ZIPCode");
+
+ custAdapter.Fill(custDataSet);
+ //
+
+ return custDataSet;
+ }
+ }
+
+ static DataSet BizTableMapping(SqlConnection connection)
+ {
+ using (connection)
+ {
+ //
+ // Assumes that connection is a valid SqlConnection object.
+ DataSet custDataSet = new DataSet();
+
+ SqlDataAdapter custAdapter = new SqlDataAdapter(
+ "SELECT * FROM dbo.Customers", connection);
+
+ // The DataTableMapping is implemented ITableMapping.
+ ITableMapping mapping =
+ custAdapter.TableMappings.Add("Table", "BizTalkSchema");
+ mapping.ColumnMappings.Add("CustomerID", "ClientID");
+ mapping.ColumnMappings.Add("CompanyName", "ClientName");
+ mapping.ColumnMappings.Add("ContactName", "Contact");
+ mapping.ColumnMappings.Add("PostalCode", "ZIP");
+
+ custAdapter.Fill(custDataSet);
+ //
+
+ return custDataSet;
+ }
+ }
+
+ static DataSet GetCustomersOrders(SqlConnection connection)
+ {
+ using (connection)
+ {
+ //
+ // Assumes that connection is a valid SqlConnection object.
+ string queryString =
+ "SELECT * FROM dbo.Customers; SELECT * FROM dbo.Orders;";
+ SqlDataAdapter adapter = new SqlDataAdapter(queryString, connection);
+
+ DataSet customersDataSet = new DataSet();
+
+ adapter.TableMappings.Add("Customers1", "Orders");
+ adapter.Fill(customersDataSet, "Customers");
+ //
+
+ return customersDataSet;
+ }
+ }
+
+ static private string GetConnectionString()
+ {
+ // To avoid storing the connection string in your code,
+ // you can retrieve it from a configuration file.
+ return "Data Source=(local);Initial Catalog=Northwind;"
+ + "Integrated Security=SSPI";
+ }
+ }
+}
diff --git a/doc/samples/SqlDataAdapter_Update.cs b/doc/samples/SqlDataAdapter_Update.cs
new file mode 100644
index 0000000000..9b1e194bd1
--- /dev/null
+++ b/doc/samples/SqlDataAdapter_Update.cs
@@ -0,0 +1,79 @@
+using System;
+using System.Data;
+using Microsoft.Data.SqlClient;
+
+class Program
+{
+ static void Main()
+ {
+ string connectionString = GetConnectionString();
+ AdapterUpdate(connectionString);
+ Console.ReadLine();
+ }
+ //
+ private static void AdapterUpdate(string connectionString)
+ {
+ using (SqlConnection connection =
+ new SqlConnection(connectionString))
+ {
+ SqlDataAdapter dataAdpater = new SqlDataAdapter(
+ "SELECT CategoryID, CategoryName FROM Categories",
+ connection);
+
+ dataAdpater.UpdateCommand = new SqlCommand(
+ "UPDATE Categories SET CategoryName = @CategoryName " +
+ "WHERE CategoryID = @CategoryID", connection);
+
+ dataAdpater.UpdateCommand.Parameters.Add(
+ "@CategoryName", SqlDbType.NVarChar, 15, "CategoryName");
+
+ SqlParameter parameter = dataAdpater.UpdateCommand.Parameters.Add(
+ "@CategoryID", SqlDbType.Int);
+ parameter.SourceColumn = "CategoryID";
+ parameter.SourceVersion = DataRowVersion.Original;
+
+ DataTable categoryTable = new DataTable();
+ dataAdpater.Fill(categoryTable);
+
+ DataRow categoryRow = categoryTable.Rows[0];
+ categoryRow["CategoryName"] = "New Beverages";
+
+ dataAdpater.Update(categoryTable);
+
+ Console.WriteLine("Rows after update.");
+ foreach (DataRow row in categoryTable.Rows)
+ {
+ {
+ Console.WriteLine("{0}: {1}", row[0], row[1]);
+ }
+ }
+ }
+ }
+ //
+
+ static void UpdateCustomers(DataSet dataSet, SqlDataAdapter adapter)
+ {
+ //
+ // Assumes that dataSet and adapter are valid objects.
+ DataTable table = dataSet.Tables["Customers"];
+
+ // First process deletes.
+ adapter.Update(table.Select(null, null, DataViewRowState.Deleted));
+
+ // Next process updates.
+ adapter.Update(table.Select(null, null,
+ DataViewRowState.ModifiedCurrent));
+
+ // Finally, process inserts.
+ adapter.Update(table.Select(null, null, DataViewRowState.Added));
+ //
+ }
+
+ static private string GetConnectionString()
+ {
+ // To avoid storing the connection string in your code,
+ // you can retrieve it from a configuration file.
+ return "Data Source=(local);Initial Catalog=Northwind;"
+ + "Integrated Security=true";
+ }
+}
From e286592cf5a3fc9d20d0f80e44287e28eb67daf0 Mon Sep 17 00:00:00 2001
From: Karina Zhou
Date: Tue, 1 Dec 2020 15:51:52 -0800
Subject: [PATCH 006/509] Add release notes for AKV v1.2.0 (#832)
* Add release notes for AKV v1.2.0
* Add release notes for AKV v1.1.1
* Minor fix
* Apply suggestions from code review
Co-authored-by: David Engel
Co-authored-by: David Engel
---
release-notes/README.md | 4 +-
.../AzureKeyVaultProvider/1.1/1.1.1.md | 36 +++++++++++++
.../AzureKeyVaultProvider/1.1/README.md | 7 +++
.../AzureKeyVaultProvider/1.2/1.2.0.md | 51 +++++++++++++++++++
.../AzureKeyVaultProvider/1.2/README.md | 7 +++
5 files changed, 104 insertions(+), 1 deletion(-)
create mode 100644 release-notes/add-ons/AzureKeyVaultProvider/1.1/1.1.1.md
create mode 100644 release-notes/add-ons/AzureKeyVaultProvider/1.1/README.md
create mode 100644 release-notes/add-ons/AzureKeyVaultProvider/1.2/1.2.0.md
create mode 100644 release-notes/add-ons/AzureKeyVaultProvider/1.2/README.md
diff --git a/release-notes/README.md b/release-notes/README.md
index fc3dcf3315..0c0c8d1b70 100644
--- a/release-notes/README.md
+++ b/release-notes/README.md
@@ -11,8 +11,10 @@ The latest stable release is [Microsoft.Data.SqlClient 2.1](2.1).
# Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider Release Notes
-The latest stable release is [Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider 1.0](add-ons/AzureKeyVaultProvider/1.0).
+The latest stable release is [Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider 1.2](add-ons/AzureKeyVaultProvider/1.2).
## Release Information
+- [Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider 1.2](add-ons/AzureKeyVaultProvider/1.2)
+- [Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider 1.1](add-ons/AzureKeyVaultProvider/1.1)
- [Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider 1.0](add-ons/AzureKeyVaultProvider/1.0)
diff --git a/release-notes/add-ons/AzureKeyVaultProvider/1.1/1.1.1.md b/release-notes/add-ons/AzureKeyVaultProvider/1.1/1.1.1.md
new file mode 100644
index 0000000000..6fd241bbbf
--- /dev/null
+++ b/release-notes/add-ons/AzureKeyVaultProvider/1.1/1.1.1.md
@@ -0,0 +1,36 @@
+# Release Notes
+
+## General Availability of Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider
+_**1.1.1 released 02 March 2020**_
+
+This library contains the implementation of `Microsoft.Data.SqlClient.SqlColumnEncryptionKeyStoreProvider` for accessing Azure Key Vault, and the provider class is named `SqlColumnEncryptionAzureKeyVaultProvider`.
+
+### Working with SQLColumnEncryptionAzureKeyVaultProvider
+`SqlColumnEncryptionAzureKeyVaultProvider` is implemented against `Microsoft.Data.SqlClient` and supports .NET Framework 4.6+ and .NET Core 2.1+. The provider name identifier for this library is "**AZURE_KEY_VAULT**" and it is not registered in the driver by default. Client applications may call the `SqlConnection.RegisterColumnEncryptionKeyStoreProviders()` API once in the lifetime of the driver to register this custom provider by implementing a custom Authentication Callback mechanism.
+
+Once the provider is registered, it can used to perform Always Encrypted operations by creating a Column Master Key using the Azure Key Vault Key Identifier URL.
+
+A sample C# application to demonstrate Always Encrypted with Azure Key Vault can be download from the samples directory: [AzureKeyVaultProviderExample.cs](https://github.com/dotnet/SqlClient/blob/master/doc/samples/AzureKeyVaultProviderExample.cs)
+
+## Target Platform Support
+
+- .NET Framework 4.6+
+- .NET Core 2.1+ (Windows x86, Windows x64, Linux, macOS)
+
+### Dependencies
+
+#### .NET Framework
+
+- Microsoft.Azure.KeyVault 3.0.4
+- Microsoft.Azure.KeyVault.WebKey 3.0.4
+- Microsoft.Data.SqlClient 1.0.19269.1
+- Microsoft.Rest.ClientRuntime 2.3.20
+- Microsoft.Rest.ClientRuntime.Azure 3.3.19
+
+#### .NET Core
+
+- Microsoft.Azure.KeyVault 3.0.4
+- Microsoft.Azure.KeyVault.WebKey 3.0.4
+- Microsoft.Data.SqlClient 1.0.19269.1
+- Microsoft.Rest.ClientRuntime 2.3.20
+- Microsoft.Rest.ClientRuntime.Azure 3.3.19
diff --git a/release-notes/add-ons/AzureKeyVaultProvider/1.1/README.md b/release-notes/add-ons/AzureKeyVaultProvider/1.1/README.md
new file mode 100644
index 0000000000..eed9f0741b
--- /dev/null
+++ b/release-notes/add-ons/AzureKeyVaultProvider/1.1/README.md
@@ -0,0 +1,7 @@
+# Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider 1.1 Releases
+
+The following Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider 1.1 stable releases have been shipped:
+
+| Release Date | Description | Notes |
+| :-- | :-- | :--: |
+| 2020/03/02 | 1.1.1 | [release notes](1.1.1.md) |
diff --git a/release-notes/add-ons/AzureKeyVaultProvider/1.2/1.2.0.md b/release-notes/add-ons/AzureKeyVaultProvider/1.2/1.2.0.md
new file mode 100644
index 0000000000..a4ed97335c
--- /dev/null
+++ b/release-notes/add-ons/AzureKeyVaultProvider/1.2/1.2.0.md
@@ -0,0 +1,51 @@
+# Release Notes
+
+## General Availability of Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider
+_**1.2.0 released 01 December 2020**_
+
+This library contains the implementation of `Microsoft.Data.SqlClient.SqlColumnEncryptionKeyStoreProvider` for accessing Azure Key Vault, and the provider class is named `SqlColumnEncryptionAzureKeyVaultProvider`.
+
+### Added
+
+- Added support for .NET Standard 2.0. This requires Microsoft.Data.SqlClient v2.1.0 and above. [#823](https://github.com/dotnet/SqlClient/pull/823)
+- Added new HSM endpoints. [#750](https://github.com/dotnet/SqlClient/pull/750)
+- Added source linked PDBs for easier debugging of the package. [#789](https://github.com/dotnet/SqlClient/pull/789)
+
+### Working with SQLColumnEncryptionAzureKeyVaultProvider
+`SqlColumnEncryptionAzureKeyVaultProvider` is implemented against `Microsoft.Data.SqlClient` and supports .NET Framework 4.6+, .NET Core 2.1+, and .NET Standard 2.0+. The provider name identifier for this library is "**AZURE_KEY_VAULT**" and it is not registered in the driver by default. Client applications may call the `SqlConnection.RegisterColumnEncryptionKeyStoreProviders()` API once in the lifetime of the driver to register this custom provider by implementing a custom Authentication Callback mechanism.
+
+Once the provider is registered, it can be used to perform Always Encrypted operations by creating a Column Master Key using the Azure Key Vault Key Identifier URL.
+
+A sample C# application to demonstrate Always Encrypted with Azure Key Vault can be download from the samples directory: [AzureKeyVaultProviderExample.cs](https://github.com/dotnet/SqlClient/blob/master/doc/samples/AzureKeyVaultProviderExample.cs)
+
+## Target Platform Support
+
+- .NET Framework 4.6+
+- .NET Core 2.1+ (Windows x86, Windows x64, Linux, macOS)
+- .NET Standard 2.0+
+
+### Dependencies
+
+#### .NET Framework
+
+- Microsoft.Azure.KeyVault 3.0.4
+- Microsoft.Azure.KeyVault.WebKey 3.0.4
+- Microsoft.Data.SqlClient 1.0.19269.1
+- Microsoft.Rest.ClientRuntime 2.3.20
+- Microsoft.Rest.ClientRuntime.Azure 3.3.19
+
+#### .NET Core
+
+- Microsoft.Azure.KeyVault 3.0.4
+- Microsoft.Azure.KeyVault.WebKey 3.0.4
+- Microsoft.Data.SqlClient 1.0.19269.1
+- Microsoft.Rest.ClientRuntime 2.3.20
+- Microsoft.Rest.ClientRuntime.Azure 3.3.19
+
+#### .NET Standard
+
+- Microsoft.Azure.KeyVault 3.0.4
+- Microsoft.Azure.KeyVault.WebKey 3.0.4
+- Microsoft.Data.SqlClient 2.1.0
+- Microsoft.Rest.ClientRuntime 2.3.20
+- Microsoft.Rest.ClientRuntime.Azure 3.3.19
diff --git a/release-notes/add-ons/AzureKeyVaultProvider/1.2/README.md b/release-notes/add-ons/AzureKeyVaultProvider/1.2/README.md
new file mode 100644
index 0000000000..43cd6f62f3
--- /dev/null
+++ b/release-notes/add-ons/AzureKeyVaultProvider/1.2/README.md
@@ -0,0 +1,7 @@
+# Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider 1.2 Releases
+
+The following Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider 1.2 stable releases have been shipped:
+
+| Release Date | Description | Notes |
+| :-- | :-- | :--: |
+| 2020/12/01 | 1.2.0 | [release notes](1.2.0.md) |
From 4f4f4124a082645cdf0b261cd96db4668592594a Mon Sep 17 00:00:00 2001
From: Cheena Malhotra
Date: Fri, 4 Dec 2020 14:55:36 -0800
Subject: [PATCH 007/509] Fix Issue with System-Assigned Managed Identity in
Azure Functions (#829)
For some reason, userId is coming as empty in this block, as reported in issue 815
---
.../SqlClient/AzureManagedIdentityAuthenticationProvider.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/AzureManagedIdentityAuthenticationProvider.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/AzureManagedIdentityAuthenticationProvider.cs
index 07174e96a8..6f543d909e 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/AzureManagedIdentityAuthenticationProvider.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/AzureManagedIdentityAuthenticationProvider.cs
@@ -89,7 +89,7 @@ public override async Task AcquireTokenAsync(SqlAuthenti
string objectIdParameter = string.Empty;
// If user assigned managed identity is specified, include object ID parameter in request
- if (parameters.UserId != default)
+ if (!string.IsNullOrWhiteSpace(parameters.UserId))
{
objectIdParameter = $"&object_id={Uri.EscapeDataString(parameters.UserId)}";
SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Identity Object id received and will be used for acquiring access token {0}", parameters.UserId);
From 59c3b102d4fae1cd10e0c39c7ccc3907f457fadd Mon Sep 17 00:00:00 2001
From: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com>
Date: Tue, 8 Dec 2020 12:55:56 -0800
Subject: [PATCH 008/509] Related samples to ADO.NET documents, importing from
.NET Framework-Part 4 (#840)
* Add samples
Related to the next part of porting documents from .NET Framework documents.
---
...SqlClient_AsyncProgramming_Cancellation.cs | 45 +++
...AsyncProgramming_DistributedTransaction.cs | 68 +++++
...lient_AsyncProgramming_MultipleCommands.cs | 72 +++++
...ent_AsyncProgramming_MultipleCommandsEx.cs | 116 ++++++++
...qlClient_AsyncProgramming_ProviderModel.cs | 46 +++
.../SqlClient_AsyncProgramming_SqlBulkCopy.cs | 275 ++++++++++++++++++
...lClient_AsyncProgramming_SqlTransaction.cs | 70 +++++
doc/samples/SqlClient_PerformanceCounter.cs | 173 +++++++++++
doc/samples/SqlClient_RetrieveIdentity.cs | 107 +++++++
doc/samples/SqlClient_Streaming_FromServer.cs | 226 ++++++++++++++
.../SqlClient_Streaming_ServerToServer.cs | 72 +++++
doc/samples/SqlClient_Streaming_ToServer.cs | 140 +++++++++
.../SqlCommand_ExecuteNonQueryAsync.cs | 27 ++
...lCommand_ExecuteReader_SequentialAccess.cs | 84 ++++++
.../SqlConnection_OpenAsync_ContinueWith.cs | 43 +++
doc/samples/SqlDataAdapter_MergeIdentity.cs | 97 ++++++
...Adapter_RetrieveIdentityStoredProcedure.cs | 71 +++++
.../SqlDataAdapter_SPIdentityReturn.cs | 70 +++++
18 files changed, 1802 insertions(+)
create mode 100644 doc/samples/SqlClient_AsyncProgramming_Cancellation.cs
create mode 100644 doc/samples/SqlClient_AsyncProgramming_DistributedTransaction.cs
create mode 100644 doc/samples/SqlClient_AsyncProgramming_MultipleCommands.cs
create mode 100644 doc/samples/SqlClient_AsyncProgramming_MultipleCommandsEx.cs
create mode 100644 doc/samples/SqlClient_AsyncProgramming_ProviderModel.cs
create mode 100644 doc/samples/SqlClient_AsyncProgramming_SqlBulkCopy.cs
create mode 100644 doc/samples/SqlClient_AsyncProgramming_SqlTransaction.cs
create mode 100644 doc/samples/SqlClient_PerformanceCounter.cs
create mode 100644 doc/samples/SqlClient_RetrieveIdentity.cs
create mode 100644 doc/samples/SqlClient_Streaming_FromServer.cs
create mode 100644 doc/samples/SqlClient_Streaming_ServerToServer.cs
create mode 100644 doc/samples/SqlClient_Streaming_ToServer.cs
create mode 100644 doc/samples/SqlCommand_ExecuteNonQueryAsync.cs
create mode 100644 doc/samples/SqlCommand_ExecuteReader_SequentialAccess.cs
create mode 100644 doc/samples/SqlConnection_OpenAsync_ContinueWith.cs
create mode 100644 doc/samples/SqlDataAdapter_MergeIdentity.cs
create mode 100644 doc/samples/SqlDataAdapter_RetrieveIdentityStoredProcedure.cs
create mode 100644 doc/samples/SqlDataAdapter_SPIdentityReturn.cs
diff --git a/doc/samples/SqlClient_AsyncProgramming_Cancellation.cs b/doc/samples/SqlClient_AsyncProgramming_Cancellation.cs
new file mode 100644
index 0000000000..d60fc6f99b
--- /dev/null
+++ b/doc/samples/SqlClient_AsyncProgramming_Cancellation.cs
@@ -0,0 +1,45 @@
+using System;
+//
+using Microsoft.Data.SqlClient;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Samples
+{
+ class CancellationSample
+ {
+ public static void Main(string[] args)
+ {
+ CancellationTokenSource source = new CancellationTokenSource();
+ source.CancelAfter(2000); // give up after 2 seconds
+ try
+ {
+ Task result = CancellingAsynchronousOperations(source.Token);
+ result.Wait();
+ }
+ catch (AggregateException exception)
+ {
+ if (exception.InnerException is SqlException)
+ {
+ Console.WriteLine("Operation canceled");
+ }
+ else
+ {
+ throw;
+ }
+ }
+ }
+
+ static async Task CancellingAsynchronousOperations(CancellationToken cancellationToken)
+ {
+ using (SqlConnection connection = new SqlConnection("Server=(local);Integrated Security=true"))
+ {
+ await connection.OpenAsync(cancellationToken);
+
+ SqlCommand command = new SqlCommand("WAITFOR DELAY '00:10:00'", connection);
+ await command.ExecuteNonQueryAsync(cancellationToken);
+ }
+ }
+ }
+}
+//
diff --git a/doc/samples/SqlClient_AsyncProgramming_DistributedTransaction.cs b/doc/samples/SqlClient_AsyncProgramming_DistributedTransaction.cs
new file mode 100644
index 0000000000..a517e0ea40
--- /dev/null
+++ b/doc/samples/SqlClient_AsyncProgramming_DistributedTransaction.cs
@@ -0,0 +1,68 @@
+using System;
+//
+using Microsoft.Data.SqlClient;
+using System.Threading.Tasks;
+using System.Transactions;
+
+class Program
+{
+ public static void Main()
+ {
+ SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
+ // replace these with your own values
+ // create two tables RegionTable1 and RegionTable2
+ // and add a constraint in one of these tables
+ // to avoid duplicate RegionID
+ builder.DataSource = "localhost";
+ builder.InitialCatalog = "Northwind";
+ builder.IntegratedSecurity = true;
+
+ Task task = ExecuteDistributedTransaction(builder.ConnectionString, builder.ConnectionString);
+ task.Wait();
+ }
+
+ static async Task ExecuteDistributedTransaction(string connectionString1, string connectionString2)
+ {
+ using (SqlConnection connection1 = new SqlConnection(connectionString1))
+ using (SqlConnection connection2 = new SqlConnection(connectionString2))
+ {
+ using (CommittableTransaction transaction = new CommittableTransaction())
+ {
+ await connection1.OpenAsync();
+ connection1.EnlistTransaction(transaction);
+
+ await connection2.OpenAsync();
+ connection2.EnlistTransaction(transaction);
+
+ try
+ {
+ SqlCommand command1 = connection1.CreateCommand();
+ command1.CommandText = "Insert into RegionTable1 (RegionID, RegionDescription) VALUES (100, 'Description')";
+ await command1.ExecuteNonQueryAsync();
+
+ SqlCommand command2 = connection2.CreateCommand();
+ command2.CommandText = "Insert into RegionTable2 (RegionID, RegionDescription) VALUES (100, 'Description')";
+ await command2.ExecuteNonQueryAsync();
+
+ transaction.Commit();
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("Exception Type: {0}", ex.GetType());
+ Console.WriteLine(" Message: {0}", ex.Message);
+
+ try
+ {
+ transaction.Rollback();
+ }
+ catch (Exception ex2)
+ {
+ Console.WriteLine("Rollback Exception Type: {0}", ex2.GetType());
+ Console.WriteLine(" Message: {0}", ex2.Message);
+ }
+ }
+ }
+ }
+ }
+}
+//
diff --git a/doc/samples/SqlClient_AsyncProgramming_MultipleCommands.cs b/doc/samples/SqlClient_AsyncProgramming_MultipleCommands.cs
new file mode 100644
index 0000000000..6f53f2b55c
--- /dev/null
+++ b/doc/samples/SqlClient_AsyncProgramming_MultipleCommands.cs
@@ -0,0 +1,72 @@
+using System;
+//
+using System.Data.Common;
+using Microsoft.Data.SqlClient;
+using System.Threading.Tasks;
+
+class Class1
+{
+ static void Main()
+ {
+ Task task = MultipleCommands();
+ task.Wait();
+ }
+
+ static async Task MultipleCommands()
+ {
+ // By default, MARS is disabled when connecting to a MARS-enabled.
+ // It must be enabled in the connection string.
+ string connectionString = GetConnectionString();
+
+ int vendorID;
+ SqlDataReader productReader = null;
+ string vendorSQL =
+ "SELECT BusinessEntityID, Name FROM Purchasing.Vendor";
+ string productSQL =
+ "SELECT Production.Product.Name FROM Production.Product " +
+ "INNER JOIN Purchasing.ProductVendor " +
+ "ON Production.Product.ProductID = " +
+ "Purchasing.ProductVendor.ProductID " +
+ "WHERE Purchasing.ProductVendor.BusinessEntityID = @VendorId";
+
+ using (SqlConnection awConnection =
+ new SqlConnection(connectionString))
+ {
+ SqlCommand vendorCmd = new SqlCommand(vendorSQL, awConnection);
+ SqlCommand productCmd =
+ new SqlCommand(productSQL, awConnection);
+
+ productCmd.Parameters.Add("@VendorId", SqlDbType.Int);
+
+ await awConnection.OpenAsync();
+ using (SqlDataReader vendorReader = await vendorCmd.ExecuteReaderAsync())
+ {
+ while (await vendorReader.ReadAsync())
+ {
+ Console.WriteLine(vendorReader["Name"]);
+
+ vendorID = (int)vendorReader["BusinessEntityID"];
+
+ productCmd.Parameters["@VendorId"].Value = vendorID;
+ // The following line of code requires a MARS-enabled connection.
+ productReader = await productCmd.ExecuteReaderAsync();
+ using (productReader)
+ {
+ while (await productReader.ReadAsync())
+ {
+ Console.WriteLine(" " +
+ productReader["Name"].ToString());
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private static string GetConnectionString()
+ {
+ // To avoid storing the connection string in your code, you can retrieve it from a configuration file.
+ return "Data Source=(local);Integrated Security=SSPI;Initial Catalog=AdventureWorks;MultipleActiveResultSets=True";
+ }
+}
+//
diff --git a/doc/samples/SqlClient_AsyncProgramming_MultipleCommandsEx.cs b/doc/samples/SqlClient_AsyncProgramming_MultipleCommandsEx.cs
new file mode 100644
index 0000000000..47376ca18c
--- /dev/null
+++ b/doc/samples/SqlClient_AsyncProgramming_MultipleCommandsEx.cs
@@ -0,0 +1,116 @@
+using System;
+//
+using System.Data.Common;
+using Microsoft.Data.SqlClient;
+using System.Threading.Tasks;
+
+class Program
+{
+ static void Main()
+ {
+ Task task = ReadingAndUpdatingData();
+ task.Wait();
+ }
+
+ static async Task ReadingAndUpdatingData()
+ {
+ // By default, MARS is disabled when connecting to a MARS-enabled host.
+ // It must be enabled in the connection string.
+ string connectionString = GetConnectionString();
+
+ SqlTransaction updateTx = null;
+ SqlCommand vendorCmd = null;
+ SqlCommand prodVendCmd = null;
+ SqlCommand updateCmd = null;
+
+ SqlDataReader prodVendReader = null;
+
+ int vendorID = 0;
+ int productID = 0;
+ int minOrderQty = 0;
+ int maxOrderQty = 0;
+ int onOrderQty = 0;
+ int recordsUpdated = 0;
+ int totalRecordsUpdated = 0;
+
+ string vendorSQL =
+ "SELECT BusinessEntityID, Name FROM Purchasing.Vendor " +
+ "WHERE CreditRating = 5";
+ string prodVendSQL =
+ "SELECT ProductID, MaxOrderQty, MinOrderQty, OnOrderQty " +
+ "FROM Purchasing.ProductVendor " +
+ "WHERE BusinessEntityID = @VendorID";
+ string updateSQL =
+ "UPDATE Purchasing.ProductVendor " +
+ "SET OnOrderQty = @OrderQty " +
+ "WHERE ProductID = @ProductID AND BusinessEntityID = @VendorID";
+
+ using (SqlConnection awConnection =
+ new SqlConnection(connectionString))
+ {
+ await awConnection.OpenAsync();
+ updateTx = await Task.Run(() => awConnection.BeginTransaction());
+
+ vendorCmd = new SqlCommand(vendorSQL, awConnection);
+ vendorCmd.Transaction = updateTx;
+
+ prodVendCmd = new SqlCommand(prodVendSQL, awConnection);
+ prodVendCmd.Transaction = updateTx;
+ prodVendCmd.Parameters.Add("@VendorId", SqlDbType.Int);
+
+ updateCmd = new SqlCommand(updateSQL, awConnection);
+ updateCmd.Transaction = updateTx;
+ updateCmd.Parameters.Add("@OrderQty", SqlDbType.Int);
+ updateCmd.Parameters.Add("@ProductID", SqlDbType.Int);
+ updateCmd.Parameters.Add("@VendorID", SqlDbType.Int);
+
+ using (SqlDataReader vendorReader = await vendorCmd.ExecuteReaderAsync())
+ {
+ while (await vendorReader.ReadAsync())
+ {
+ Console.WriteLine(vendorReader["Name"]);
+
+ vendorID = (int)vendorReader["BusinessEntityID"];
+ prodVendCmd.Parameters["@VendorID"].Value = vendorID;
+ prodVendReader = await prodVendCmd.ExecuteReaderAsync();
+
+ using (prodVendReader)
+ {
+ while (await prodVendReader.ReadAsync())
+ {
+ productID = (int)prodVendReader["ProductID"];
+
+ if (prodVendReader["OnOrderQty"] == DBNull.Value)
+ {
+ minOrderQty = (int)prodVendReader["MinOrderQty"];
+ onOrderQty = minOrderQty;
+ }
+ else
+ {
+ maxOrderQty = (int)prodVendReader["MaxOrderQty"];
+ onOrderQty = (int)(maxOrderQty / 2);
+ }
+
+ updateCmd.Parameters["@OrderQty"].Value = onOrderQty;
+ updateCmd.Parameters["@ProductID"].Value = productID;
+ updateCmd.Parameters["@VendorID"].Value = vendorID;
+
+ recordsUpdated = await updateCmd.ExecuteNonQueryAsync();
+ totalRecordsUpdated += recordsUpdated;
+ }
+ }
+ }
+ }
+ Console.WriteLine("Total Records Updated: ", totalRecordsUpdated.ToString());
+ await Task.Run(() => updateTx.Rollback());
+ Console.WriteLine("Transaction Rolled Back");
+ }
+ }
+
+ private static string GetConnectionString()
+ {
+ // To avoid storing the connection string in your code, you can retrieve it from a configuration file.
+ return "Data Source=(local);Integrated Security=SSPI;Initial Catalog=AdventureWorks;MultipleActiveResultSets=True";
+ }
+}
+//
diff --git a/doc/samples/SqlClient_AsyncProgramming_ProviderModel.cs b/doc/samples/SqlClient_AsyncProgramming_ProviderModel.cs
new file mode 100644
index 0000000000..7653e3947d
--- /dev/null
+++ b/doc/samples/SqlClient_AsyncProgramming_ProviderModel.cs
@@ -0,0 +1,46 @@
+using System;
+//
+using System.Data.Common;
+using Microsoft.Data.SqlClient;
+using System.Threading.Tasks;
+
+class program
+{
+ static async Task PerformDBOperationsUsingProviderModel(string connectionString)
+ {
+ using (DbConnection connection = SqlClientFactory.Instance.CreateConnection())
+ {
+ connection.ConnectionString = connectionString;
+ await connection.OpenAsync();
+
+ DbCommand command = connection.CreateCommand();
+ command.CommandText = "SELECT * FROM AUTHORS";
+
+ using (DbDataReader reader = await command.ExecuteReaderAsync())
+ {
+ while (await reader.ReadAsync())
+ {
+ for (int i = 0; i < reader.FieldCount; i++)
+ {
+ // Process each column as appropriate
+ object obj = await reader.GetFieldValueAsync
diff --git a/doc/samples/SqlClient_AsyncProgramming_SqlBulkCopy.cs b/doc/samples/SqlClient_AsyncProgramming_SqlBulkCopy.cs
new file mode 100644
index 0000000000..7a383410fc
--- /dev/null
+++ b/doc/samples/SqlClient_AsyncProgramming_SqlBulkCopy.cs
@@ -0,0 +1,275 @@
+using System;
+//
+using System.Data;
+using Microsoft.Data.SqlClient;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace SqlBulkCopyAsyncCodeSample
+{
+ class Program
+ {
+ static string selectStatement = "SELECT * FROM [pubs].[dbo].[titles]";
+ static string createDestTableStatement =
+ @"CREATE TABLE {0} (
+ [title_id] [varchar](6) NOT NULL,
+ [title] [varchar](80) NOT NULL,
+ [type] [char](12) NOT NULL,
+ [pub_id] [char](4) NULL,
+ [price] [money] NULL,
+ [advance] [money] NULL,
+ [royalty] [int] NULL,
+ [ytd_sales] [int] NULL,
+ [notes] [varchar](200) NULL,
+ [pubdate] [datetime] NOT NULL)";
+
+ // Replace the connection string if needed, for instance to connect to SQL Express: @"Server=(local)\SQLEXPRESS;Database=Demo;Integrated Security=true"
+ // static string connectionString = @"Server=(localdb)\V11.0;Database=Demo";
+ static string connectionString = @"Server=(local);Database=Demo;Integrated Security=true";
+
+ // static string marsConnectionString = @"Server=(localdb)\V11.0;Database=Demo;MultipleActiveResultSets=true;";
+ static string marsConnectionString = @"Server=(local);Database=Demo;MultipleActiveResultSets=true;Integrated Security=true";
+
+ // Replace the Server name with your actual sql azure server name and User ID/Password
+ static string azureConnectionString = @"Server=SqlAzure;User ID=;Password=;Database=Demo";
+
+ static void Main(string[] args)
+ {
+ SynchronousSqlBulkCopy();
+ AsyncSqlBulkCopy().Wait();
+ MixSyncAsyncSqlBulkCopy().Wait();
+ AsyncSqlBulkCopyNotifyAfter().Wait();
+ AsyncSqlBulkCopyDataRows().Wait();
+ AsyncSqlBulkCopySqlServerToSqlAzure().Wait();
+ AsyncSqlBulkCopyCancel().Wait();
+ AsyncSqlBulkCopyMARS().Wait();
+ }
+
+ // 3.1.1 Synchronous bulk copy in .NET 4.5
+ private static void SynchronousSqlBulkCopy()
+ {
+ using (SqlConnection conn = new SqlConnection(connectionString))
+ {
+ conn.Open();
+ DataTable dt = new DataTable();
+ using (SqlCommand cmd = new SqlCommand(selectStatement, conn))
+ {
+ SqlDataAdapter adapter = new SqlDataAdapter(cmd);
+ adapter.Fill(dt);
+
+ string temptable = "[#" + Guid.NewGuid().ToString("N") + "]";
+ cmd.CommandText = string.Format(createDestTableStatement, temptable);
+ cmd.ExecuteNonQuery();
+
+ using (SqlBulkCopy bcp = new SqlBulkCopy(conn))
+ {
+ bcp.DestinationTableName = temptable;
+ bcp.WriteToServer(dt);
+ }
+ }
+ }
+
+ }
+
+ // 3.1.2 Asynchronous bulk copy in .NET 4.5
+ private static async Task AsyncSqlBulkCopy()
+ {
+ using (SqlConnection conn = new SqlConnection(connectionString))
+ {
+ await conn.OpenAsync();
+ DataTable dt = new DataTable();
+ using (SqlCommand cmd = new SqlCommand(selectStatement, conn))
+ {
+ SqlDataAdapter adapter = new SqlDataAdapter(cmd);
+ adapter.Fill(dt);
+
+ string temptable = "[#" + Guid.NewGuid().ToString("N") + "]";
+ cmd.CommandText = string.Format(createDestTableStatement, temptable);
+ await cmd.ExecuteNonQueryAsync();
+
+ using (SqlBulkCopy bcp = new SqlBulkCopy(conn))
+ {
+ bcp.DestinationTableName = temptable;
+ await bcp.WriteToServerAsync(dt);
+ }
+ }
+ }
+ }
+
+ // 3.2 Add new Async.NET capabilities in an existing application (Mixing synchronous and asynchronous calls)
+ private static async Task MixSyncAsyncSqlBulkCopy()
+ {
+ using (SqlConnection conn1 = new SqlConnection(connectionString))
+ {
+ conn1.Open();
+ using (SqlCommand cmd = new SqlCommand(selectStatement, conn1))
+ {
+ using (SqlDataReader reader = cmd.ExecuteReader())
+ {
+ using (SqlConnection conn2 = new SqlConnection(connectionString))
+ {
+ await conn2.OpenAsync();
+ string temptable = "[#" + Guid.NewGuid().ToString("N") + "]";
+ SqlCommand createCmd = new SqlCommand(string.Format(createDestTableStatement, temptable), conn2);
+ await createCmd.ExecuteNonQueryAsync();
+ using (SqlBulkCopy bcp = new SqlBulkCopy(conn2))
+ {
+ bcp.DestinationTableName = temptable;
+ await bcp.WriteToServerAsync(reader);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // 3.3 Using the NotifyAfter property
+ private static async Task AsyncSqlBulkCopyNotifyAfter()
+ {
+ using (SqlConnection conn = new SqlConnection(connectionString))
+ {
+ await conn.OpenAsync();
+ DataTable dt = new DataTable();
+ using (SqlCommand cmd = new SqlCommand(selectStatement, conn))
+ {
+ SqlDataAdapter adapter = new SqlDataAdapter(cmd);
+ adapter.Fill(dt);
+
+ string temptable = "[#" + Guid.NewGuid().ToString("N") + "]";
+ cmd.CommandText = string.Format(createDestTableStatement, temptable);
+ await cmd.ExecuteNonQueryAsync();
+
+ using (SqlBulkCopy bcp = new SqlBulkCopy(conn))
+ {
+ bcp.DestinationTableName = temptable;
+ bcp.NotifyAfter = 5;
+ bcp.SqlRowsCopied += new SqlRowsCopiedEventHandler(OnSqlRowsCopied);
+ await bcp.WriteToServerAsync(dt);
+ }
+ }
+ }
+ }
+
+ private static void OnSqlRowsCopied(object sender, SqlRowsCopiedEventArgs e)
+ {
+ Console.WriteLine("Copied {0} so far...", e.RowsCopied);
+ }
+
+ // 3.4 Using the new SqlBulkCopy Async.NET capabilities with DataRow[]
+ private static async Task AsyncSqlBulkCopyDataRows()
+ {
+ using (SqlConnection conn = new SqlConnection(connectionString))
+ {
+ await conn.OpenAsync();
+ DataTable dt = new DataTable();
+ using (SqlCommand cmd = new SqlCommand(selectStatement, conn))
+ {
+ SqlDataAdapter adapter = new SqlDataAdapter(cmd);
+ adapter.Fill(dt);
+ DataRow[] rows = dt.Select();
+
+ string temptable = "[#" + Guid.NewGuid().ToString("N") + "]";
+ cmd.CommandText = string.Format(createDestTableStatement, temptable);
+ await cmd.ExecuteNonQueryAsync();
+
+ using (SqlBulkCopy bcp = new SqlBulkCopy(conn))
+ {
+ bcp.DestinationTableName = temptable;
+ await bcp.WriteToServerAsync(rows);
+ }
+ }
+ }
+ }
+
+ // 3.5 Copying data from SQL Server to SQL Azure in .NET 4.5
+ private static async Task AsyncSqlBulkCopySqlServerToSqlAzure()
+ {
+ using (SqlConnection srcConn = new SqlConnection(connectionString))
+ using (SqlConnection destConn = new SqlConnection(azureConnectionString))
+ {
+ await srcConn.OpenAsync();
+ await destConn.OpenAsync();
+ using (SqlCommand srcCmd = new SqlCommand(selectStatement, srcConn))
+ {
+ using (SqlDataReader reader = await srcCmd.ExecuteReaderAsync())
+ {
+ string temptable = "[#" + Guid.NewGuid().ToString("N") + "]";
+ using (SqlCommand destCmd = new SqlCommand(string.Format(createDestTableStatement, temptable), destConn))
+ {
+ await destCmd.ExecuteNonQueryAsync();
+ using (SqlBulkCopy bcp = new SqlBulkCopy(destConn))
+ {
+ bcp.DestinationTableName = temptable;
+ await bcp.WriteToServerAsync(reader);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // 3.6 Cancelling an Asynchronous Operation to SQL Azure
+ private static async Task AsyncSqlBulkCopyCancel()
+ {
+ CancellationTokenSource cts = new CancellationTokenSource();
+ using (SqlConnection srcConn = new SqlConnection(connectionString))
+ using (SqlConnection destConn = new SqlConnection(azureConnectionString))
+ {
+ await srcConn.OpenAsync(cts.Token);
+ await destConn.OpenAsync(cts.Token);
+ using (SqlCommand srcCmd = new SqlCommand(selectStatement, srcConn))
+ {
+ using (SqlDataReader reader = await srcCmd.ExecuteReaderAsync(cts.Token))
+ {
+ string temptable = "[#" + Guid.NewGuid().ToString("N") + "]";
+ using (SqlCommand destCmd = new SqlCommand(string.Format(createDestTableStatement, temptable), destConn))
+ {
+ await destCmd.ExecuteNonQueryAsync(cts.Token);
+ using (SqlBulkCopy bcp = new SqlBulkCopy(destConn))
+ {
+ bcp.DestinationTableName = temptable;
+ await bcp.WriteToServerAsync(reader, cts.Token);
+ //Cancel Async SqlBulCopy Operation after 200 ms
+ cts.CancelAfter(200);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // 3.7 Using Async.Net and MARS
+ private static async Task AsyncSqlBulkCopyMARS()
+ {
+ using (SqlConnection marsConn = new SqlConnection(marsConnectionString))
+ {
+ await marsConn.OpenAsync();
+
+ SqlCommand titlesCmd = new SqlCommand("SELECT * FROM [pubs].[dbo].[titles]", marsConn);
+ SqlCommand authorsCmd = new SqlCommand("SELECT * FROM [pubs].[dbo].[authors]", marsConn);
+ //With MARS we can have multiple active results sets on the same connection
+ using (SqlDataReader titlesReader = await titlesCmd.ExecuteReaderAsync())
+ using (SqlDataReader authorsReader = await authorsCmd.ExecuteReaderAsync())
+ {
+ await authorsReader.ReadAsync();
+
+ string temptable = "[#" + Guid.NewGuid().ToString("N") + "]";
+ using (SqlConnection destConn = new SqlConnection(connectionString))
+ {
+ await destConn.OpenAsync();
+ using (SqlCommand destCmd = new SqlCommand(string.Format(createDestTableStatement, temptable), destConn))
+ {
+ await destCmd.ExecuteNonQueryAsync();
+ using (SqlBulkCopy bcp = new SqlBulkCopy(destConn))
+ {
+ bcp.DestinationTableName = temptable;
+ await bcp.WriteToServerAsync(titlesReader);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+//
diff --git a/doc/samples/SqlClient_AsyncProgramming_SqlTransaction.cs b/doc/samples/SqlClient_AsyncProgramming_SqlTransaction.cs
new file mode 100644
index 0000000000..86659b3c98
--- /dev/null
+++ b/doc/samples/SqlClient_AsyncProgramming_SqlTransaction.cs
@@ -0,0 +1,70 @@
+using System;
+//
+using Microsoft.Data.SqlClient;
+using System.Threading.Tasks;
+
+class Program
+{
+ static void Main()
+ {
+ string connectionString =
+ "Persist Security Info=False;Integrated Security=SSPI;database=Northwind;server=(local)";
+ Task task = ExecuteSqlTransaction(connectionString);
+ task.Wait();
+ }
+
+ static async Task ExecuteSqlTransaction(string connectionString)
+ {
+ using (SqlConnection connection = new SqlConnection(connectionString))
+ {
+ await connection.OpenAsync();
+
+ SqlCommand command = connection.CreateCommand();
+ SqlTransaction transaction = null;
+
+ // Start a local transaction.
+ transaction = await Task.Run(
+ () => connection.BeginTransaction("SampleTransaction")
+ );
+
+ // Must assign both transaction object and connection
+ // to Command object for a pending local transaction
+ command.Connection = connection;
+ command.Transaction = transaction;
+
+ try {
+ command.CommandText =
+ "Insert into Region (RegionID, RegionDescription) VALUES (555, 'Description')";
+ await command.ExecuteNonQueryAsync();
+
+ command.CommandText =
+ "Insert into Region (RegionID, RegionDescription) VALUES (556, 'Description')";
+ await command.ExecuteNonQueryAsync();
+
+ // Attempt to commit the transaction.
+ await Task.Run(() => transaction.Commit());
+ Console.WriteLine("Both records are written to database.");
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("Commit Exception Type: {0}", ex.GetType());
+ Console.WriteLine(" Message: {0}", ex.Message);
+
+ // Attempt to roll back the transaction.
+ try
+ {
+ transaction.Rollback();
+ }
+ catch (Exception ex2)
+ {
+ // This catch block will handle any errors that may have occurred
+ // on the server that would cause the rollback to fail, such as
+ // a closed connection.
+ Console.WriteLine("Rollback Exception Type: {0}", ex2.GetType());
+ Console.WriteLine(" Message: {0}", ex2.Message);
+ }
+ }
+ }
+ }
+}
+//
diff --git a/doc/samples/SqlClient_PerformanceCounter.cs b/doc/samples/SqlClient_PerformanceCounter.cs
new file mode 100644
index 0000000000..e015d6f6b1
--- /dev/null
+++ b/doc/samples/SqlClient_PerformanceCounter.cs
@@ -0,0 +1,173 @@
+//
+using System;
+using Microsoft.Data.SqlClient;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+
+namespace PerformanceCounterTest
+{
+ class Program
+ {
+ PerformanceCounter[] PerfCounters = new PerformanceCounter[10];
+ SqlConnection connection = new SqlConnection();
+
+ static void Main()
+ {
+ Program prog = new Program();
+ // Open a connection and create the performance counters.
+ prog.connection.ConnectionString =
+ GetIntegratedSecurityConnectionString();
+ prog.SetUpPerformanceCounters();
+ Console.WriteLine("Available Performance Counters:");
+
+ // Create the connections and display the results.
+ prog.CreateConnections();
+ Console.WriteLine("Press Enter to finish.");
+ Console.ReadLine();
+ }
+
+ private void CreateConnections()
+ {
+ // List the Performance counters.
+ WritePerformanceCounters();
+
+ // Create 4 connections and display counter information.
+ SqlConnection connection1 = new SqlConnection(
+ GetIntegratedSecurityConnectionString());
+ connection1.Open();
+ Console.WriteLine("Opened the 1st Connection:");
+ WritePerformanceCounters();
+
+ SqlConnection connection2 = new SqlConnection(
+ GetSqlConnectionStringDifferent());
+ connection2.Open();
+ Console.WriteLine("Opened the 2nd Connection:");
+ WritePerformanceCounters();
+
+ SqlConnection connection3 = new SqlConnection(
+ GetSqlConnectionString());
+ connection3.Open();
+ Console.WriteLine("Opened the 3rd Connection:");
+ WritePerformanceCounters();
+
+ SqlConnection connection4 = new SqlConnection(
+ GetSqlConnectionString());
+ connection4.Open();
+ Console.WriteLine("Opened the 4th Connection:");
+ WritePerformanceCounters();
+
+ connection1.Close();
+ Console.WriteLine("Closed the 1st Connection:");
+ WritePerformanceCounters();
+
+ connection2.Close();
+ Console.WriteLine("Closed the 2nd Connection:");
+ WritePerformanceCounters();
+
+ connection3.Close();
+ Console.WriteLine("Closed the 3rd Connection:");
+ WritePerformanceCounters();
+
+ connection4.Close();
+ Console.WriteLine("Closed the 4th Connection:");
+ WritePerformanceCounters();
+ }
+
+ private enum ADO_Net_Performance_Counters
+ {
+ NumberOfActiveConnectionPools,
+ NumberOfReclaimedConnections,
+ HardConnectsPerSecond,
+ HardDisconnectsPerSecond,
+ NumberOfActiveConnectionPoolGroups,
+ NumberOfInactiveConnectionPoolGroups,
+ NumberOfInactiveConnectionPools,
+ NumberOfNonPooledConnections,
+ NumberOfPooledConnections,
+ NumberOfStasisConnections
+ // The following performance counters are more expensive to track.
+ // Enable ConnectionPoolPerformanceCounterDetail in your config file.
+ // SoftConnectsPerSecond
+ // SoftDisconnectsPerSecond
+ // NumberOfActiveConnections
+ // NumberOfFreeConnections
+ }
+
+ private void SetUpPerformanceCounters()
+ {
+ connection.Close();
+ this.PerfCounters = new PerformanceCounter[10];
+ string instanceName = GetInstanceName();
+ Type apc = typeof(ADO_Net_Performance_Counters);
+ int i = 0;
+ foreach (string s in Enum.GetNames(apc))
+ {
+ this.PerfCounters[i] = new PerformanceCounter();
+ this.PerfCounters[i].CategoryName = ".NET Data Provider for SqlServer";
+ this.PerfCounters[i].CounterName = s;
+ this.PerfCounters[i].InstanceName = instanceName;
+ i++;
+ }
+ }
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ static extern int GetCurrentProcessId();
+
+ private string GetInstanceName()
+ {
+ //This works for Winforms apps.
+ string instanceName =
+ System.Reflection.Assembly.GetEntryAssembly().GetName().Name;
+
+ // Must replace special characters like (, ), #, /, \\
+ string instanceName2 =
+ AppDomain.CurrentDomain.FriendlyName.ToString().Replace('(', '[')
+ .Replace(')', ']').Replace('#', '_').Replace('/', '_').Replace('\\', '_');
+
+ // For ASP.NET applications your instanceName will be your CurrentDomain's
+ // FriendlyName. Replace the line above that sets the instanceName with this:
+ // instanceName = AppDomain.CurrentDomain.FriendlyName.ToString().Replace('(','[')
+ // .Replace(')',']').Replace('#','_').Replace('/','_').Replace('\\','_');
+
+ string pid = GetCurrentProcessId().ToString();
+ instanceName = instanceName + "[" + pid + "]";
+ Console.WriteLine("Instance Name: {0}", instanceName);
+ Console.WriteLine("---------------------------");
+ return instanceName;
+ }
+
+ private void WritePerformanceCounters()
+ {
+ Console.WriteLine("---------------------------");
+ foreach (PerformanceCounter p in this.PerfCounters)
+ {
+ Console.WriteLine("{0} = {1}", p.CounterName, p.NextValue());
+ }
+ Console.WriteLine("---------------------------");
+ }
+
+ private static string GetIntegratedSecurityConnectionString()
+ {
+ // To avoid storing the connection string in your code,
+ // you can retrieve it from a configuration file.
+ return @"Data Source=.;Integrated Security=True;" +
+ "Initial Catalog=AdventureWorks";
+ }
+ private static string GetSqlConnectionString()
+ {
+ // To avoid storing the connection string in your code,
+ // you can retrieve it from a configuration file.
+ return @"Data Source=.;User Id=;Password=;" +
+ "Initial Catalog=AdventureWorks";
+ }
+
+ private static string GetSqlConnectionStringDifferent()
+ {
+ // To avoid storing the connection string in your code,
+ // you can retrieve it from a configuration file.
+ return @"Initial Catalog=AdventureWorks;Data Source=.;" +
+ "User Id=;Password=;";
+ }
+ }
+}
+//
diff --git a/doc/samples/SqlClient_RetrieveIdentity.cs b/doc/samples/SqlClient_RetrieveIdentity.cs
new file mode 100644
index 0000000000..ba08be607a
--- /dev/null
+++ b/doc/samples/SqlClient_RetrieveIdentity.cs
@@ -0,0 +1,107 @@
+using System;
+using System.Data;
+using Microsoft.Data.SqlClient;
+
+namespace AutoNumberTest
+{
+ class Program
+ {
+ //
+ static void Main(string[] args)
+ {
+ String SqlDbConnectionString = "Data Source=(local);Initial Catalog=MySchool;Integrated Security=True;";
+
+ InsertPersonInCommand(SqlDbConnectionString, "Janice", "Galvin");
+ Console.WriteLine();
+
+ InsertPersonInAdapter(SqlDbConnectionString, "Peter", "Krebs");
+ Console.WriteLine();
+
+ Console.WriteLine("Please press any key to exit.....");
+ Console.ReadKey();
+ }
+
+ // Using stored procedure to insert a new row and retrieve the identity value
+ static void InsertPersonInCommand(String connectionString, String firstName, String lastName)
+ {
+ String commandText = "dbo.InsertPerson";
+
+ using (SqlConnection conn = new SqlConnection(connectionString))
+ {
+ using (SqlCommand cmd = new SqlCommand(commandText, conn))
+ {
+ cmd.CommandType = CommandType.StoredProcedure;
+
+ cmd.Parameters.Add(new SqlParameter("@FirstName", firstName));
+ cmd.Parameters.Add(new SqlParameter("@LastName", lastName));
+ SqlParameter personId = new SqlParameter("@PersonID", SqlDbType.Int);
+ personId.Direction = ParameterDirection.Output;
+ cmd.Parameters.Add(personId);
+
+ conn.Open();
+ cmd.ExecuteNonQuery();
+
+ Console.WriteLine("Person Id of new person:{0}", personId.Value);
+ }
+ }
+ }
+
+ // Using stored procedure in adapter to insert new rows and update the identity value.
+ static void InsertPersonInAdapter(String connectionString, String firstName, String lastName)
+ {
+ String commandText = "dbo.InsertPerson";
+ using (SqlConnection conn = new SqlConnection(connectionString))
+ {
+ SqlDataAdapter mySchool = new SqlDataAdapter("Select PersonID,FirstName,LastName from [dbo].[Person]", conn);
+
+ mySchool.InsertCommand = new SqlCommand(commandText, conn);
+ mySchool.InsertCommand.CommandType = CommandType.StoredProcedure;
+
+ mySchool.InsertCommand.Parameters.Add(
+ new SqlParameter("@FirstName", SqlDbType.NVarChar, 50, "FirstName"));
+ mySchool.InsertCommand.Parameters.Add(
+ new SqlParameter("@LastName", SqlDbType.NVarChar, 50, "LastName"));
+
+ SqlParameter personId = mySchool.InsertCommand.Parameters.Add(new SqlParameter("@PersonID", SqlDbType.Int, 0, "PersonID"));
+ personId.Direction = ParameterDirection.Output;
+
+ DataTable persons = new DataTable();
+ mySchool.Fill(persons);
+
+ DataRow newPerson = persons.NewRow();
+ newPerson["FirstName"] = firstName;
+ newPerson["LastName"] = lastName;
+ persons.Rows.Add(newPerson);
+
+ mySchool.Update(persons);
+ Console.WriteLine("Show all persons:");
+ ShowDataTable(persons, 14);
+ }
+ }
+
+ private static void ShowDataTable(DataTable table, Int32 length)
+ {
+ foreach (DataColumn col in table.Columns)
+ {
+ Console.Write("{0,-" + length + "}", col.ColumnName);
+ }
+ Console.WriteLine();
+
+ foreach (DataRow row in table.Rows)
+ {
+ foreach (DataColumn col in table.Columns)
+ {
+ if (col.DataType.Equals(typeof(DateTime)))
+ Console.Write("{0,-" + length + ":d}", row[col]);
+ else if (col.DataType.Equals(typeof(Decimal)))
+ Console.Write("{0,-" + length + ":C}", row[col]);
+ else
+ Console.Write("{0,-" + length + "}", row[col]);
+ }
+
+ Console.WriteLine();
+ }
+ }
+ //
+ }
+}
diff --git a/doc/samples/SqlClient_Streaming_FromServer.cs b/doc/samples/SqlClient_Streaming_FromServer.cs
new file mode 100644
index 0000000000..a139b828e6
--- /dev/null
+++ b/doc/samples/SqlClient_Streaming_FromServer.cs
@@ -0,0 +1,226 @@
+//
+using System;
+using System.Data;
+using Microsoft.Data.SqlClient;
+using System.IO;
+using System.Threading.Tasks;
+using System.Xml;
+
+namespace StreamingFromServer
+{
+ class Program
+ {
+ private const string connectionString = @"Server=localhost;Database=Demo;Integrated Security=true";
+
+ static void Main(string[] args)
+ {
+ CopyBinaryValueToFile().Wait();
+ PrintTextValues().Wait();
+ PrintXmlValues().Wait();
+ PrintXmlValuesViaNVarChar().Wait();
+
+ Console.WriteLine("Done");
+ }
+
+ // Application retrieving a large BLOB from SQL Server in .NET 4.5 using the new asynchronous capability
+ private static async Task CopyBinaryValueToFile()
+ {
+ using (SqlConnection connection = new SqlConnection(connectionString))
+ {
+ await connection.OpenAsync();
+ using (SqlCommand command = new SqlCommand("SELECT [bindata] FROM [Streams] WHERE [id]=@id", connection))
+ {
+ command.Parameters.AddWithValue("id", 1);
+
+ // The reader needs to be executed with the SequentialAccess behavior to enable network streaming
+ // Otherwise ReadAsync will buffer the entire BLOB into memory which can cause scalability issues or even OutOfMemoryExceptions
+ using (SqlDataReader reader = await command.ExecuteReaderAsync(CommandBehavior.SequentialAccess))
+ {
+ if (await reader.ReadAsync())
+ {
+ if (!(await reader.IsDBNullAsync(0)))
+ {
+ using (FileStream file = new FileStream("binarydata.bin", FileMode.Create, FileAccess.Write))
+ {
+ using (Stream data = reader.GetStream(0))
+ {
+
+ // Asynchronously copy the stream from the server to the file we just created
+ await data.CopyToAsync(file);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Application transferring a large Text File from SQL Server
+ private static async Task PrintTextValues()
+ {
+ using (SqlConnection connection = new SqlConnection(connectionString))
+ {
+ await connection.OpenAsync();
+ using (SqlCommand command = new SqlCommand("SELECT [id], [textdata] FROM [Streams]", connection))
+ {
+
+ // The reader needs to be executed with the SequentialAccess behavior to enable network streaming
+ // Otherwise ReadAsync will buffer the entire text document into memory which can cause scalability issues or even OutOfMemoryExceptions
+ using (SqlDataReader reader = await command.ExecuteReaderAsync(CommandBehavior.SequentialAccess))
+ {
+ while (await reader.ReadAsync())
+ {
+ Console.Write("{0}: ", reader.GetInt32(0));
+
+ if (await reader.IsDBNullAsync(1))
+ {
+ Console.Write("(NULL)");
+ }
+ else
+ {
+ char[] buffer = new char[4096];
+ int charsRead = 0;
+ using (TextReader data = reader.GetTextReader(1))
+ {
+ do
+ {
+ // Grab each chunk of text and write it to the console
+ // If you are writing to a TextWriter you should use WriteAsync or WriteLineAsync
+ charsRead = await data.ReadAsync(buffer, 0, buffer.Length);
+ Console.Write(buffer, 0, charsRead);
+ } while (charsRead > 0);
+ }
+ }
+
+ Console.WriteLine();
+ }
+ }
+ }
+ }
+ }
+
+ // Application transferring a large Xml Document from SQL Server
+ private static async Task PrintXmlValues()
+ {
+ using (SqlConnection connection = new SqlConnection(connectionString))
+ {
+ await connection.OpenAsync();
+ using (SqlCommand command = new SqlCommand("SELECT [id], [xmldata] FROM [Streams]", connection))
+ {
+
+ // The reader needs to be executed with the SequentialAccess behavior to enable network streaming
+ // Otherwise ReadAsync will buffer the entire Xml Document into memory which can cause scalability issues or even OutOfMemoryExceptions
+ using (SqlDataReader reader = await command.ExecuteReaderAsync(CommandBehavior.SequentialAccess))
+ {
+ while (await reader.ReadAsync())
+ {
+ Console.WriteLine("{0}: ", reader.GetInt32(0));
+
+ if (await reader.IsDBNullAsync(1))
+ {
+ Console.WriteLine("\t(NULL)");
+ }
+ else
+ {
+ using (XmlReader xmlReader = reader.GetXmlReader(1))
+ {
+ int depth = 1;
+ // NOTE: The XmlReader returned by GetXmlReader does NOT support async operations
+ // See the example below (PrintXmlValuesViaNVarChar) for how to get an XmlReader with asynchronous capabilities
+ while (xmlReader.Read())
+ {
+ switch (xmlReader.NodeType)
+ {
+ case XmlNodeType.Element:
+ Console.WriteLine("{0}<{1}>", new string('\t', depth), xmlReader.Name);
+ depth++;
+ break;
+ case XmlNodeType.Text:
+ Console.WriteLine("{0}{1}", new string('\t', depth), xmlReader.Value);
+ break;
+ case XmlNodeType.EndElement:
+ depth--;
+ Console.WriteLine("{0}{1}>", new string('\t', depth), xmlReader.Name);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Application transferring a large Xml Document from SQL Server
+ // This goes via NVarChar and TextReader to enable asynchronous reading
+ private static async Task PrintXmlValuesViaNVarChar()
+ {
+ XmlReaderSettings xmlSettings = new XmlReaderSettings()
+ {
+ // Async must be explicitly enabled in the XmlReaderSettings otherwise the XmlReader will throw exceptions when async methods are called
+ Async = true,
+ // Since we will immediately wrap the TextReader we are creating in an XmlReader, we will permit the XmlReader to take care of closing\disposing it
+ CloseInput = true,
+ // If the Xml you are reading is not a valid document (as per ) you will need to set the conformance level to Fragment
+ ConformanceLevel = ConformanceLevel.Fragment
+ };
+
+ using (SqlConnection connection = new SqlConnection(connectionString))
+ {
+ await connection.OpenAsync();
+
+ // Cast the XML into NVarChar to enable GetTextReader - trying to use GetTextReader on an XML type will throw an exception
+ using (SqlCommand command = new SqlCommand("SELECT [id], CAST([xmldata] AS NVARCHAR(MAX)) FROM [Streams]", connection))
+ {
+
+ // The reader needs to be executed with the SequentialAccess behavior to enable network streaming
+ // Otherwise ReadAsync will buffer the entire Xml Document into memory which can cause scalability issues or even OutOfMemoryExceptions
+ using (SqlDataReader reader = await command.ExecuteReaderAsync(CommandBehavior.SequentialAccess))
+ {
+ while (await reader.ReadAsync())
+ {
+ Console.WriteLine("{0}:", reader.GetInt32(0));
+
+ if (await reader.IsDBNullAsync(1))
+ {
+ Console.WriteLine("\t(NULL)");
+ }
+ else
+ {
+ // Grab the row as a TextReader, then create an XmlReader on top of it
+ // We are not keeping a reference to the TextReader since the XmlReader is created with the "CloseInput" setting (so it will close the TextReader when needed)
+ using (XmlReader xmlReader = XmlReader.Create(reader.GetTextReader(1), xmlSettings))
+ {
+ int depth = 1;
+ // The XmlReader above now supports asynchronous operations, so we can use ReadAsync here
+ while (await xmlReader.ReadAsync())
+ {
+ switch (xmlReader.NodeType)
+ {
+ case XmlNodeType.Element:
+ Console.WriteLine("{0}<{1}>", new string('\t', depth), xmlReader.Name);
+ depth++;
+ break;
+ case XmlNodeType.Text:
+ // Depending on what your data looks like, you should either use Value or GetValueAsync
+ // Value has less overhead (since it doesn't create a Task), but it may also block if additional data is required
+ Console.WriteLine("{0}{1}", new string('\t', depth), await xmlReader.GetValueAsync());
+ break;
+ case XmlNodeType.EndElement:
+ depth--;
+ Console.WriteLine("{0}{1}>", new string('\t', depth), xmlReader.Name);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+//
diff --git a/doc/samples/SqlClient_Streaming_ServerToServer.cs b/doc/samples/SqlClient_Streaming_ServerToServer.cs
new file mode 100644
index 0000000000..42efe6fa32
--- /dev/null
+++ b/doc/samples/SqlClient_Streaming_ServerToServer.cs
@@ -0,0 +1,72 @@
+//
+using System;
+using System.Data;
+using Microsoft.Data.SqlClient;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace StreamingFromServerToAnother
+{
+ class Program
+ {
+ private const string connectionString = @"Server=localhost;Database=Demo2;Integrated Security=true";
+
+ static void Main(string[] args)
+ {
+ // For this example, we don't want to cancel
+ // So we can pass in a "blank" cancellation token
+ E2EStream(CancellationToken.None).Wait();
+
+ Console.WriteLine("Done");
+ }
+
+ // Streaming from one SQL Server to Another One
+ private static async Task E2EStream(CancellationToken cancellationToken)
+ {
+ using (SqlConnection readConn = new SqlConnection(connectionString))
+ {
+ using (SqlConnection writeConn = new SqlConnection(connectionString))
+ {
+
+ // Note that we are using the same cancellation token for calls to both connections\commands
+ // Also we can start both the connection opening asynchronously, and then wait for both to complete
+ Task openReadConn = readConn.OpenAsync(cancellationToken);
+ Task openWriteConn = writeConn.OpenAsync(cancellationToken);
+ await Task.WhenAll(openReadConn, openWriteConn);
+
+ using (SqlCommand readCmd = new SqlCommand("SELECT [bindata] FROM [BinaryStreams]", readConn))
+ {
+ using (SqlCommand writeCmd = new SqlCommand("INSERT INTO [BinaryStreamsCopy] (bindata) VALUES (@bindata)", writeConn))
+ {
+
+ // Add an empty parameter to the write command which will be used for the streams we are copying
+ // Size is set to -1 to indicate "MAX"
+ SqlParameter streamParameter = writeCmd.Parameters.Add("@bindata", SqlDbType.Binary, -1);
+
+ // The reader needs to be executed with the SequentialAccess behavior to enable network streaming
+ // Otherwise ReadAsync will buffer the entire BLOB into memory which can cause scalability issues or even OutOfMemoryExceptions
+ using (SqlDataReader reader = await readCmd.ExecuteReaderAsync(CommandBehavior.SequentialAccess, cancellationToken))
+ {
+ while (await reader.ReadAsync(cancellationToken))
+ {
+ // Grab a stream to the binary data in the source database
+ using (Stream dataStream = reader.GetStream(0))
+ {
+
+ // Set the parameter value to the stream source that was opened
+ streamParameter.Value = dataStream;
+
+ // Asynchronously send data from one database to another
+ await writeCmd.ExecuteNonQueryAsync(cancellationToken);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+//
diff --git a/doc/samples/SqlClient_Streaming_ToServer.cs b/doc/samples/SqlClient_Streaming_ToServer.cs
new file mode 100644
index 0000000000..6ee858db1c
--- /dev/null
+++ b/doc/samples/SqlClient_Streaming_ToServer.cs
@@ -0,0 +1,140 @@
+//
+using System;
+using System.Data;
+using Microsoft.Data.SqlClient;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace StreamingToServer
+{
+ class Program
+ {
+ private const string connectionString = @"Server=localhost;Database=Demo2;Integrated Security=true";
+
+ static void Main(string[] args)
+ {
+ CreateDemoFiles();
+
+ StreamBLOBToServer().Wait();
+ StreamTextToServer().Wait();
+
+ // Create a CancellationTokenSource that will be cancelled after 100ms
+ // Typically this token source will be cancelled by a user request (e.g. a Cancel button)
+ CancellationTokenSource tokenSource = new CancellationTokenSource();
+ tokenSource.CancelAfter(100);
+ try
+ {
+ CancelBLOBStream(tokenSource.Token).Wait();
+ }
+ catch (AggregateException ex)
+ {
+ // Cancelling an async operation will throw an exception
+ // Since we are using the Task's Wait method, this exception will be wrapped in an AggregateException
+ // If you were using the 'await' keyword, the compiler would take care of unwrapping the AggregateException
+ // Depending on when the cancellation occurs, you can either get an error from SQL Server or from .Net
+ if ((ex.InnerException is SqlException) || (ex.InnerException is TaskCanceledException))
+ {
+ // This is an expected exception
+ Console.WriteLine("Got expected exception: {0}", ex.InnerException.Message);
+ }
+ else
+ {
+ // Did not expect this exception - re-throw it
+ throw;
+ }
+ }
+
+ Console.WriteLine("Done");
+ }
+
+ // This is used to generate the files which are used by the other sample methods
+ private static void CreateDemoFiles()
+ {
+ Random rand = new Random();
+ byte[] data = new byte[1024];
+ rand.NextBytes(data);
+
+ using (FileStream file = File.Open("binarydata.bin", FileMode.Create))
+ {
+ file.Write(data, 0, data.Length);
+ }
+
+ using (StreamWriter writer = new StreamWriter(File.Open("textdata.txt", FileMode.Create)))
+ {
+ writer.Write(Convert.ToBase64String(data));
+ }
+ }
+
+ // Application transferring a large BLOB to SQL Server
+ private static async Task StreamBLOBToServer()
+ {
+ using (SqlConnection conn = new SqlConnection(connectionString))
+ {
+ await conn.OpenAsync();
+ using (SqlCommand cmd = new SqlCommand("INSERT INTO [BinaryStreams] (bindata) VALUES (@bindata)", conn))
+ {
+ using (FileStream file = File.Open("binarydata.bin", FileMode.Open))
+ {
+
+ // Add a parameter which uses the FileStream we just opened
+ // Size is set to -1 to indicate "MAX"
+ cmd.Parameters.Add("@bindata", SqlDbType.Binary, -1).Value = file;
+
+ // Send the data to the server asynchronously
+ await cmd.ExecuteNonQueryAsync();
+ }
+ }
+ }
+ }
+
+ // Application transferring a large Text File to SQL Server
+ private static async Task StreamTextToServer()
+ {
+ using (SqlConnection conn = new SqlConnection(connectionString))
+ {
+ await conn.OpenAsync();
+ using (SqlCommand cmd = new SqlCommand("INSERT INTO [TextStreams] (textdata) VALUES (@textdata)", conn))
+ {
+ using (StreamReader file = File.OpenText("textdata.txt"))
+ {
+
+ // Add a parameter which uses the StreamReader we just opened
+ // Size is set to -1 to indicate "MAX"
+ cmd.Parameters.Add("@textdata", SqlDbType.NVarChar, -1).Value = file;
+
+ // Send the data to the server asynchronously
+ await cmd.ExecuteNonQueryAsync();
+ }
+ }
+ }
+ }
+
+ // Cancelling the transfer of a large BLOB
+ private static async Task CancelBLOBStream(CancellationToken cancellationToken)
+ {
+ using (SqlConnection conn = new SqlConnection(connectionString))
+ {
+ // We can cancel not only sending the data to the server, but also opening the connection
+ await conn.OpenAsync(cancellationToken);
+
+ // Artificially delay the command by 100ms
+ using (SqlCommand cmd = new SqlCommand("WAITFOR DELAY '00:00:00:100';INSERT INTO [BinaryStreams] (bindata) VALUES (@bindata)", conn))
+ {
+ using (FileStream file = File.Open("binarydata.bin", FileMode.Open))
+ {
+
+ // Add a parameter which uses the FileStream we just opened
+ // Size is set to -1 to indicate "MAX"
+ cmd.Parameters.Add("@bindata", SqlDbType.Binary, -1).Value = file;
+
+ // Send the data to the server asynchronously
+ // Pass the cancellation token such that the command will be cancelled if needed
+ await cmd.ExecuteNonQueryAsync(cancellationToken);
+ }
+ }
+ }
+ }
+ }
+}
+//
diff --git a/doc/samples/SqlCommand_ExecuteNonQueryAsync.cs b/doc/samples/SqlCommand_ExecuteNonQueryAsync.cs
new file mode 100644
index 0000000000..d1f8fc5db8
--- /dev/null
+++ b/doc/samples/SqlCommand_ExecuteNonQueryAsync.cs
@@ -0,0 +1,27 @@
+using System;
+//
+using Microsoft.Data.SqlClient;
+using System.Threading.Tasks;
+
+class A {
+ public static void Main()
+ {
+ using (SqlConnection conn = new SqlConnection("Data Source=(local); Initial Catalog=NorthWind; Integrated Security=SSPI"))
+ {
+ SqlCommand command = new SqlCommand("SELECT TOP 2 * FROM dbo.Orders", conn);
+
+ int result = A.Method(conn, command).Result;
+
+ SqlDataReader reader = command.ExecuteReader();
+ while (reader.Read())
+ Console.WriteLine(reader[0]);
+ }
+ }
+
+ static async Task Method(SqlConnection conn, SqlCommand cmd) {
+ await conn.OpenAsync();
+ await cmd.ExecuteNonQueryAsync();
+ return 1;
+ }
+}
+//
diff --git a/doc/samples/SqlCommand_ExecuteReader_SequentialAccess.cs b/doc/samples/SqlCommand_ExecuteReader_SequentialAccess.cs
new file mode 100644
index 0000000000..864e183428
--- /dev/null
+++ b/doc/samples/SqlCommand_ExecuteReader_SequentialAccess.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Data;
+using Microsoft.Data.SqlClient;
+
+class Program
+{
+ static void Main()
+ {
+ string cnnString = "Data Source=(local);Initial Catalog=pubs;"
+ + "Integrated Security=SSPI";
+ SqlConnection connection = new SqlConnection(cnnString);
+ RetrievePubLogo(connection);
+ }
+
+ private static void RetrievePubLogo(SqlConnection connection)
+ {
+ //
+ // Assumes that connection is a valid SqlConnection object.
+ SqlCommand command = new SqlCommand(
+ "SELECT pub_id, logo FROM pub_info", connection);
+
+ // Writes the BLOB to a file (*.bmp).
+ System.IO.FileStream stream;
+ // Streams the BLOB to the FileStream object.
+ System.IO.BinaryWriter writer;
+
+ // Size of the BLOB buffer.
+ int bufferSize = 100;
+ // The BLOB byte[] buffer to be filled by GetBytes.
+ byte[] outByte = new byte[bufferSize];
+ // The bytes returned from GetBytes.
+ long retval;
+ // The starting position in the BLOB output.
+ long startIndex = 0;
+
+ // The publisher id to use in the file name.
+ string pubID = "";
+
+ // Open the connection and read data into the DataReader.
+ connection.Open();
+ SqlDataReader reader = command.ExecuteReader(CommandBehavior.SequentialAccess);
+
+ while (reader.Read())
+ {
+ // Get the publisher id, which must occur before getting the logo.
+ pubID = reader.GetString(0);
+
+ // Create a file to hold the output.
+ stream = new System.IO.FileStream(
+ "logo" + pubID + ".bmp", System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write);
+ writer = new System.IO.BinaryWriter(stream);
+
+ // Reset the starting byte for the new BLOB.
+ startIndex = 0;
+
+ // Read bytes into outByte[] and retain the number of bytes returned.
+ retval = reader.GetBytes(1, startIndex, outByte, 0, bufferSize);
+
+ // Continue while there are bytes beyond the size of the buffer.
+ while (retval == bufferSize)
+ {
+ writer.Write(outByte);
+ writer.Flush();
+
+ // Reposition start index to end of last buffer and fill buffer.
+ startIndex += bufferSize;
+ retval = reader.GetBytes(1, startIndex, outByte, 0, bufferSize);
+ }
+
+ // Write the remaining buffer.
+ writer.Write(outByte, 0, (int)retval);
+ writer.Flush();
+
+ // Close the output file.
+ writer.Close();
+ stream.Close();
+ }
+
+ // Close the reader and the connection.
+ reader.Close();
+ connection.Close();
+ //
+ }
+}
diff --git a/doc/samples/SqlConnection_OpenAsync_ContinueWith.cs b/doc/samples/SqlConnection_OpenAsync_ContinueWith.cs
new file mode 100644
index 0000000000..1bc63d3af0
--- /dev/null
+++ b/doc/samples/SqlConnection_OpenAsync_ContinueWith.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Data;
+//
+using Microsoft.Data.SqlClient;
+using System.Threading.Tasks;
+
+class A
+{
+ static void ProductList(IAsyncResult result) { }
+
+ public static void Main()
+ {
+ // AsyncCallback productList = new AsyncCallback(ProductList);
+ // SqlConnection conn = new SqlConnection("Data Source=(local); Initial Catalog=NorthWind; Integrated Security=SSPI");
+ // conn.Open();
+ // SqlCommand cmd = new SqlCommand("select top 2 * from orders", conn);
+ // IAsyncResult ia = cmd.BeginExecuteReader(productList, cmd);
+
+ AsyncCallback productList = new AsyncCallback(ProductList);
+ SqlConnection conn = new SqlConnection("Data Source=(local); Initial Catalog=NorthWind; Integrated Security=SSPI");
+ conn.OpenAsync().ContinueWith((task) => {
+ SqlCommand cmd = new SqlCommand("select top 2 * from orders", conn);
+ IAsyncResult ia = cmd.BeginExecuteReader(productList, cmd);
+ }, TaskContinuationOptions.OnlyOnRanToCompletion);
+ }
+}
+//
+
+class B
+{
+ static void ProductList(IAsyncResult result) { }
+
+ public static void Main()
+ {
+ //
+ AsyncCallback productList = new AsyncCallback(ProductList);
+ SqlConnection conn = new SqlConnection("Data Source=(local); Initial Catalog=NorthWind; Integrated Security=SSPI");
+ conn.Open();
+ SqlCommand cmd = new SqlCommand("select top 2 * from orders", conn);
+ IAsyncResult ia = cmd.BeginExecuteReader(productList, cmd);
+ //
+ }
+}
diff --git a/doc/samples/SqlDataAdapter_MergeIdentity.cs b/doc/samples/SqlDataAdapter_MergeIdentity.cs
new file mode 100644
index 0000000000..010beda2c7
--- /dev/null
+++ b/doc/samples/SqlDataAdapter_MergeIdentity.cs
@@ -0,0 +1,97 @@
+using System;
+using System.Data;
+using Microsoft.Data.SqlClient;
+
+class Program
+{
+ static void Main()
+ {
+ string connectionString = GetConnectionString();
+ MergeIdentityColumns(connectionString);
+ Console.ReadLine();
+ }
+
+ //
+ private static void MergeIdentityColumns(string connectionString)
+ {
+ using (SqlConnection connection = new SqlConnection(connectionString))
+ {
+ // Create the DataAdapter
+ SqlDataAdapter adapter = new SqlDataAdapter(
+ "SELECT ShipperID, CompanyName FROM dbo.Shippers",
+ connection);
+
+ //Add the InsertCommand to retrieve new identity value.
+ adapter.InsertCommand = new SqlCommand(
+ "INSERT INTO dbo.Shippers (CompanyName) " +
+ "VALUES (@CompanyName); " +
+ "SELECT ShipperID, CompanyName FROM dbo.Shippers " +
+ "WHERE ShipperID = SCOPE_IDENTITY();", connection);
+
+ // Add the parameter for the inserted value.
+ adapter.InsertCommand.Parameters.Add(
+ new SqlParameter("@CompanyName", SqlDbType.NVarChar, 40,
+ "CompanyName"));
+ adapter.InsertCommand.UpdatedRowSource = UpdateRowSource.Both;
+
+ // MissingSchemaAction adds any missing schema to
+ // the DataTable, including identity columns
+ adapter.MissingSchemaAction = MissingSchemaAction.AddWithKey;
+
+ // Fill the DataTable.
+ DataTable shipper = new DataTable();
+ adapter.Fill(shipper);
+
+ // Add a new shipper.
+ DataRow newRow = shipper.NewRow();
+ newRow["CompanyName"] = "New Shipper";
+ shipper.Rows.Add(newRow);
+
+ // Add changed rows to a new DataTable. This
+ // DataTable will be used by the DataAdapter.
+ DataTable dataChanges = shipper.GetChanges();
+
+ // Add the event handler.
+ adapter.RowUpdated +=
+ new SqlRowUpdatedEventHandler(OnRowUpdated);
+
+ adapter.Update(dataChanges);
+ connection.Close();
+
+ // Merge the updates.
+ shipper.Merge(dataChanges);
+
+ // Commit the changes.
+ shipper.AcceptChanges();
+
+ Console.WriteLine("Rows after merge.");
+ foreach (DataRow row in shipper.Rows)
+ {
+ {
+ Console.WriteLine("{0}: {1}", row[0], row[1]);
+ }
+ }
+ }
+ }
+ //
+
+ //
+ protected static void OnRowUpdated(
+ object sender, SqlRowUpdatedEventArgs e)
+ {
+ // If this is an insert, then skip this row.
+ if (e.StatementType == StatementType.Insert)
+ {
+ e.Status = UpdateStatus.SkipCurrentRow;
+ }
+ }
+ //
+
+ static private string GetConnectionString()
+ {
+ // To avoid storing the connection string in your code,
+ // you can retrieve it from a configuration file.
+ return "Data Source=(local);Initial Catalog=Northwind;"
+ + "Integrated Security=true";
+ }
+}
diff --git a/doc/samples/SqlDataAdapter_RetrieveIdentityStoredProcedure.cs b/doc/samples/SqlDataAdapter_RetrieveIdentityStoredProcedure.cs
new file mode 100644
index 0000000000..976de4e3b1
--- /dev/null
+++ b/doc/samples/SqlDataAdapter_RetrieveIdentityStoredProcedure.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Data;
+using Microsoft.Data.SqlClient;
+
+class Program
+{
+ static void Main()
+ {
+ string connectionString = GetConnectionString();
+ RetrieveIdentity(connectionString);
+ Console.ReadLine();
+ }
+
+ //
+ private static void RetrieveIdentity(string connectionString)
+ {
+ using (SqlConnection connection = new SqlConnection(connectionString))
+ {
+ // Create a SqlDataAdapter based on a SELECT query.
+ SqlDataAdapter adapter = new SqlDataAdapter(
+ "SELECT CategoryID, CategoryName FROM dbo.Categories",
+ connection);
+
+ //Create the SqlCommand to execute the stored procedure.
+ adapter.InsertCommand = new SqlCommand("dbo.InsertCategory",
+ connection);
+ adapter.InsertCommand.CommandType = CommandType.StoredProcedure;
+
+ // Add the parameter for the CategoryName. Specifying the
+ // ParameterDirection for an input parameter is not required.
+ adapter.InsertCommand.Parameters.Add(
+ new SqlParameter("@CategoryName", SqlDbType.NVarChar, 15,
+ "CategoryName"));
+
+ // Add the SqlParameter to retrieve the new identity value.
+ // Specify the ParameterDirection as Output.
+ SqlParameter parameter =
+ adapter.InsertCommand.Parameters.Add(
+ "@Identity", SqlDbType.Int, 0, "CategoryID");
+ parameter.Direction = ParameterDirection.Output;
+
+ // Create a DataTable and fill it.
+ DataTable categories = new DataTable();
+ adapter.Fill(categories);
+
+ // Add a new row.
+ DataRow newRow = categories.NewRow();
+ newRow["CategoryName"] = "New Category";
+ categories.Rows.Add(newRow);
+
+ adapter.Update(categories);
+
+ Console.WriteLine("List All Rows:");
+ foreach (DataRow row in categories.Rows)
+ {
+ {
+ Console.WriteLine("{0}: {1}", row[0], row[1]);
+ }
+ }
+ }
+ }
+ //
+
+ static private string GetConnectionString()
+ {
+ // To avoid storing the connection string in your code,
+ // you can retrieve it from a configuration file.
+ return "Data Source=(local);Initial Catalog=Northwind;"
+ + "Integrated Security=true";
+ }
+}
diff --git a/doc/samples/SqlDataAdapter_SPIdentityReturn.cs b/doc/samples/SqlDataAdapter_SPIdentityReturn.cs
new file mode 100644
index 0000000000..41628b5478
--- /dev/null
+++ b/doc/samples/SqlDataAdapter_SPIdentityReturn.cs
@@ -0,0 +1,70 @@
+//
+using System;
+using System.Data;
+using Microsoft.Data.SqlClient;
+
+class Program
+{
+ static void Main()
+ {
+ string connectionString = GetConnectionString();
+ ReturnIdentity(connectionString);
+ // Console.ReadLine();
+ }
+
+ private static void ReturnIdentity(string connectionString)
+ {
+ using (SqlConnection connection = new SqlConnection(connectionString))
+ {
+ // Create a SqlDataAdapter based on a SELECT query.
+ SqlDataAdapter adapter = new SqlDataAdapter(
+ "SELECT CategoryID, CategoryName FROM dbo.Categories", connection);
+
+ // Create a SqlCommand to execute the stored procedure.
+ adapter.InsertCommand = new SqlCommand("InsertCategory", connection);
+ adapter.InsertCommand.CommandType = CommandType.StoredProcedure;
+
+ // Create a parameter for the ReturnValue.
+ SqlParameter parameter = adapter.InsertCommand.Parameters.Add("@RowCount", SqlDbType.Int);
+ parameter.Direction = ParameterDirection.ReturnValue;
+
+ // Create an input parameter for the CategoryName.
+ // You do not need to specify direction for input parameters.
+ adapter.InsertCommand.Parameters.Add("@CategoryName", SqlDbType.NChar, 15, "CategoryName");
+
+ // Create an output parameter for the new identity value.
+ parameter = adapter.InsertCommand.Parameters.Add("@Identity", SqlDbType.Int, 0, "CategoryID");
+ parameter.Direction = ParameterDirection.Output;
+
+ // Create a DataTable and fill it.
+ DataTable categories = new DataTable();
+ adapter.Fill(categories);
+
+ // Add a new row.
+ DataRow categoryRow = categories.NewRow();
+ categoryRow["CategoryName"] = "New Beverages";
+ categories.Rows.Add(categoryRow);
+
+ // Update the database.
+ adapter.Update(categories);
+
+ // Retrieve the ReturnValue.
+ Int rowCount = (Int)adapter.InsertCommand.Parameters["@RowCount"].Value;
+
+ Console.WriteLine("ReturnValue: {0}", rowCount.ToString());
+ Console.WriteLine("All Rows:");
+ foreach (DataRow row in categories.Rows)
+ {
+ Console.WriteLine(" {0}: {1}", row[0], row[1]);
+ }
+ }
+ }
+
+ static private string GetConnectionString()
+ {
+ // To avoid storing the connection string in your code,
+ // you can retrieve it from a configuration file.
+ return "Data Source=(local);Initial Catalog=Northwind;Integrated Security=true";
+ }
+}
+//
From 25a3f4dddd2327378179acefb129736569e29e92 Mon Sep 17 00:00:00 2001
From: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com>
Date: Thu, 10 Dec 2020 17:02:46 -0800
Subject: [PATCH 009/509] State the deprecated properties (#842)
* Move obsolete properties out
* Asynchronous Processing
* Context Connection
* Update src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs
---
.../SqlCommand_BeginExecuteNonQuery.cs | 5 +-
.../SqlCommand_BeginExecuteNonQueryForm.cs | 5 +-
...Command_BeginExecuteReaderAsyncBehavior.cs | 4 +-
...qlCommand_BeginExecuteReaderAsyncSimple.cs | 5 +-
.../SqlCommand_BeginExecuteXmlReader.cs | 5 +-
.../SqlCommand_BeginExecuteXmlReaderAsync.cs | 4 +-
doc/samples/SqlCommand_Intro.cs | 2 +-
doc/samples/SqlConnectionStringBuilder.cs | 1 -
...ionStringBuilder_AsynchronousProcessing.cs | 88 -------------------
.../SqlConnectionStringBuilder_Values.cs | 2 +-
doc/samples/SqlConnection_GetSchema.cs | 2 +-
doc/samples/TransactionIsolationLevels.cs | 2 +-
.../Microsoft.Data.SqlClient/SqlBulkCopy.xml | 19 ----
.../Microsoft.Data.SqlClient/SqlCommand.xml | 82 -----------------
.../SqlConnection.xml | 19 +---
.../SqlConnectionStringBuilder.xml | 17 ++--
.../SqlCredential.xml | 2 -
.../SqlDataReader.xml | 21 ++---
.../netfx/ref/Microsoft.Data.SqlClient.cs | 4 +-
.../SqlClient/SqlConnectionStringBuilder.cs | 14 ++-
.../Data/SqlClient/SqlDependencyListener.cs | 2 +
21 files changed, 38 insertions(+), 267 deletions(-)
delete mode 100644 doc/samples/SqlConnectionStringBuilder_AsynchronousProcessing.cs
diff --git a/doc/samples/SqlCommand_BeginExecuteNonQuery.cs b/doc/samples/SqlCommand_BeginExecuteNonQuery.cs
index 4598ffcd38..7cae30238f 100644
--- a/doc/samples/SqlCommand_BeginExecuteNonQuery.cs
+++ b/doc/samples/SqlCommand_BeginExecuteNonQuery.cs
@@ -75,11 +75,8 @@ private static string GetConnectionString()
// To avoid storing the connection string in your code,
// you can retrieve it from a configuration file.
- // If you have not included "Asynchronous Processing=true" in the
- // connection string, the command is not able
- // to execute asynchronously.
return "Data Source=(local);Integrated Security=SSPI;" +
- "Initial Catalog=AdventureWorks; Asynchronous Processing=true";
+ "Initial Catalog=AdventureWorks";
}
}
//
diff --git a/doc/samples/SqlCommand_BeginExecuteNonQueryForm.cs b/doc/samples/SqlCommand_BeginExecuteNonQueryForm.cs
index 5bc740978a..d800ebde16 100644
--- a/doc/samples/SqlCommand_BeginExecuteNonQueryForm.cs
+++ b/doc/samples/SqlCommand_BeginExecuteNonQueryForm.cs
@@ -49,11 +49,8 @@ private static string GetConnectionString()
// To avoid storing the connection string in your code,
// you can retrieve it from a configuration file.
- // If you have not included "Asynchronous Processing=true" in the
- // connection string, the command is not able
- // to execute asynchronously.
return "Data Source=(local);Integrated Security=true;" +
- "Initial Catalog=AdventureWorks; Asynchronous Processing=true";
+ "Initial Catalog=AdventureWorks";
}
private void DisplayStatus(string Text)
diff --git a/doc/samples/SqlCommand_BeginExecuteReaderAsyncBehavior.cs b/doc/samples/SqlCommand_BeginExecuteReaderAsyncBehavior.cs
index 830bf36be7..a79254fbbc 100644
--- a/doc/samples/SqlCommand_BeginExecuteReaderAsyncBehavior.cs
+++ b/doc/samples/SqlCommand_BeginExecuteReaderAsyncBehavior.cs
@@ -119,10 +119,8 @@ private string GetConnectionString()
// To avoid storing the connection string in your code,
// you can retrieve it from a configuration file.
- // If you do not include the Asynchronous Processing=true name/value pair,
- // you wo not be able to execute the command asynchronously.
return "Data Source=(local);Integrated Security=true;" +
- "Initial Catalog=AdventureWorks; Asynchronous Processing=true";
+ "Initial Catalog=AdventureWorks";
}
private void button1_Click(object sender, System.EventArgs e)
diff --git a/doc/samples/SqlCommand_BeginExecuteReaderAsyncSimple.cs b/doc/samples/SqlCommand_BeginExecuteReaderAsyncSimple.cs
index c010b16c06..2c5d74a8f4 100644
--- a/doc/samples/SqlCommand_BeginExecuteReaderAsyncSimple.cs
+++ b/doc/samples/SqlCommand_BeginExecuteReaderAsyncSimple.cs
@@ -92,11 +92,8 @@ private static string GetConnectionString()
// To avoid storing the connection string in your code,
// you can retrieve it from a configuration file.
- // If you have not included "Asynchronous Processing=true" in the
- // connection string, the command is not able
- // to execute asynchronously.
return "Data Source=(local);Integrated Security=true;" +
- "Initial Catalog=AdventureWorks; Asynchronous Processing=true";
+ "Initial Catalog=AdventureWorks";
}
}
//
diff --git a/doc/samples/SqlCommand_BeginExecuteXmlReader.cs b/doc/samples/SqlCommand_BeginExecuteXmlReader.cs
index 9f99c070a9..6935d7d117 100644
--- a/doc/samples/SqlCommand_BeginExecuteXmlReader.cs
+++ b/doc/samples/SqlCommand_BeginExecuteXmlReader.cs
@@ -75,11 +75,8 @@ private static string GetConnectionString()
// To avoid storing the connection string in your code,
// you can retrieve it from a configuration file.
- // If you have not included "Asynchronous Processing=true" in the
- // connection string, the command is not able
- // to execute asynchronously.
return "Data Source=(local);Integrated Security=true;" +
- "Initial Catalog=AdventureWorks; Asynchronous Processing=true";
+ "Initial Catalog=AdventureWorks";
}
}
//
diff --git a/doc/samples/SqlCommand_BeginExecuteXmlReaderAsync.cs b/doc/samples/SqlCommand_BeginExecuteXmlReaderAsync.cs
index b3ba1902ae..35195c95a7 100644
--- a/doc/samples/SqlCommand_BeginExecuteXmlReaderAsync.cs
+++ b/doc/samples/SqlCommand_BeginExecuteXmlReaderAsync.cs
@@ -37,10 +37,8 @@ private string GetConnectionString()
// To avoid storing the connection string in your code,
// you can retrieve it from a configuration file.
- // If you do not include the Asynchronous Processing=true name/value pair,
- // you wo not be able to execute the command asynchronously.
return "Data Source=(local);Integrated Security=true;" +
- "Initial Catalog=AdventureWorks; Asynchronous Processing=true";
+ "Initial Catalog=AdventureWorks";
}
private void DisplayStatus(string Text)
diff --git a/doc/samples/SqlCommand_Intro.cs b/doc/samples/SqlCommand_Intro.cs
index b0af57ffa3..5c16f78fd5 100644
--- a/doc/samples/SqlCommand_Intro.cs
+++ b/doc/samples/SqlCommand_Intro.cs
@@ -68,7 +68,7 @@ public static SqlDataReader ExecuteReader(String connectionString, String comman
static void Main(string[] args)
{
- String connectionString = "Data Source=(local);Initial Catalog=MySchool;Integrated Security=True;Asynchronous Processing=true;";
+ String connectionString = "Data Source=(local);Initial Catalog=MySchool;Integrated Security=True;";
CountCourses(connectionString, 2012);
Console.WriteLine();
diff --git a/doc/samples/SqlConnectionStringBuilder.cs b/doc/samples/SqlConnectionStringBuilder.cs
index bb19d43b16..f1c3252880 100644
--- a/doc/samples/SqlConnectionStringBuilder.cs
+++ b/doc/samples/SqlConnectionStringBuilder.cs
@@ -27,7 +27,6 @@ static void Main()
// you can work with individual items.
Console.WriteLine(builder.Password);
builder.Password = "new@1Password";
- builder.AsynchronousProcessing = true;
// You can refer to connection keys using strings,
// as well. When you use this technique (the default
diff --git a/doc/samples/SqlConnectionStringBuilder_AsynchronousProcessing.cs b/doc/samples/SqlConnectionStringBuilder_AsynchronousProcessing.cs
deleted file mode 100644
index b3706e86bd..0000000000
--- a/doc/samples/SqlConnectionStringBuilder_AsynchronousProcessing.cs
+++ /dev/null
@@ -1,88 +0,0 @@
-using System;
-using System.Data;
-//
-using Microsoft.Data.SqlClient;
-using System.Threading;
-
-class Program
-{
- static void Main()
- {
- // Create a SqlConnectionStringBuilder instance,
- // and ensure that it is set up for asynchronous processing.
- SqlConnectionStringBuilder builder =
- new SqlConnectionStringBuilder(GetConnectionString());
- // Asynchronous method calls won't work unless you
- // have added this option, or have added
- // the clause "Asynchronous Processing=true"
- // to the connection string.
- builder.AsynchronousProcessing = true;
-
- string commandText =
- "UPDATE Production.Product SET ReorderPoint = ReorderPoint + 1 " +
- "WHERE ReorderPoint IS NOT Null;" +
- "WAITFOR DELAY '0:0:3';" +
- "UPDATE Production.Product SET ReorderPoint = ReorderPoint - 1 " +
- "WHERE ReorderPoint IS NOT Null";
- RunCommandAsynchronously(commandText, builder.ConnectionString);
-
- Console.WriteLine("Press any key to finish.");
- Console.ReadLine();
- }
-
- private static string GetConnectionString()
- {
- // To avoid storing the connection string in your code,
- // you can retrieve it from a configuration file.
- return "Data Source=(local);Integrated Security=SSPI;" +
- "Initial Catalog=AdventureWorks";
- }
-
- private static void RunCommandAsynchronously(string commandText,
- string connectionString)
- {
- // Given command text and connection string, asynchronously execute
- // the specified command against the connection. For this example,
- // the code displays an indicator as it's working, verifying the
- // asynchronous behavior.
- using (SqlConnection connection = new SqlConnection(connectionString))
- {
- try
- {
- int count = 0;
- SqlCommand command = new SqlCommand(commandText, connection);
- connection.Open();
- IAsyncResult result = command.BeginExecuteNonQuery();
- while (!result.IsCompleted)
- {
- Console.WriteLine("Waiting {0}.", count);
- // Wait for 1/10 second, so the counter
- // doesn't consume all available resources
- // on the main thread.
- Thread.Sleep(100);
- count += 1;
- }
- Console.WriteLine("Command complete. Affected {0} rows.",
- command.EndExecuteNonQuery(result));
-
- }
- catch (SqlException ex)
- {
- Console.WriteLine(
- "Error {0}: Microsoft.Data.SqlClient.SqlConnectionStringBuilder",
- ex.Number, ex.Message);
- }
- catch (InvalidOperationException ex)
- {
- Console.WriteLine("Error: {0}", ex.Message);
- }
- catch (Exception ex)
- {
- // You might want to pass these errors
- // back out to the caller.
- Console.WriteLine("Error: {0}", ex.Message);
- }
- }
- }
-}
-//
diff --git a/doc/samples/SqlConnectionStringBuilder_Values.cs b/doc/samples/SqlConnectionStringBuilder_Values.cs
index ae6f3b0f32..553a02e5fb 100644
--- a/doc/samples/SqlConnectionStringBuilder_Values.cs
+++ b/doc/samples/SqlConnectionStringBuilder_Values.cs
@@ -23,7 +23,7 @@ private static string GetConnectionString()
// To avoid storing the connection string in your code,
// you can retrieve it from a configuration file.
return "Data Source=(local);Integrated Security=SSPI;" +
- "Initial Catalog=AdventureWorks; Asynchronous Processing=true";
+ "Initial Catalog=AdventureWorks";
}
}
//
diff --git a/doc/samples/SqlConnection_GetSchema.cs b/doc/samples/SqlConnection_GetSchema.cs
index 64b07aaef5..8ca75b225e 100644
--- a/doc/samples/SqlConnection_GetSchema.cs
+++ b/doc/samples/SqlConnection_GetSchema.cs
@@ -7,7 +7,7 @@ class Program
{
static void Main(string[] args)
{
- using (SqlConnection conn = new SqlConnection("Data Source=(local);Initial Catalog=MySchool;Integrated Security=True;Asynchronous Processing=true;"))
+ using (SqlConnection conn = new SqlConnection("Data Source=(local);Initial Catalog=MySchool;Integrated Security=True;"))
{
conn.Open();
diff --git a/doc/samples/TransactionIsolationLevels.cs b/doc/samples/TransactionIsolationLevels.cs
index dc85d9447b..6abd99e15d 100644
--- a/doc/samples/TransactionIsolationLevels.cs
+++ b/doc/samples/TransactionIsolationLevels.cs
@@ -487,7 +487,7 @@ class TransactionIsolationLevelsProgram
{
internal static void Main(string[] args)
{
- String connString = "Data Source=(local);Initial Catalog=master;Integrated Security=True;Asynchronous Processing=true;";
+ String connString = "Data Source=(local);Initial Catalog=master;Integrated Security=True;";
OperateDatabase.CreateDatabase(connString);
Console.WriteLine();
diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlBulkCopy.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlBulkCopy.xml
index 6247136669..970d74c289 100644
--- a/doc/snippets/Microsoft.Data.SqlClient/SqlBulkCopy.xml
+++ b/doc/snippets/Microsoft.Data.SqlClient/SqlBulkCopy.xml
@@ -780,8 +780,6 @@ For more information about asynchronous programming in the .NET Framework Data P
Returned in the task object, the
object is closed before method execution.
-
- is specified in the connection string.
A
@@ -850,9 +848,6 @@ For more information about asynchronous programming in the .NET Framework Data P
object is closed before method execution.
-
- is specified in the connection string.
-
A
did not specify a valid destination column name.
@@ -921,8 +916,6 @@ For more information about asynchronous programming in the .NET Framework Data P
's associated connection was closed before the completed
returned.
-
- is specified in the connection string.
A
@@ -1026,8 +1019,6 @@ For more information about asynchronous programming in the .NET Framework Data P
's associated connection was closed before the completed
returned.
-
- is specified in the connection string.
A
@@ -1106,8 +1097,6 @@ For more information about asynchronous programming in the .NET Framework Data P
's associated connection was closed before the completed
returned.
-
- is specified in the connection string.
A
@@ -1167,8 +1156,6 @@ For more information about asynchronous programming in the .NET Framework Data P
Returned in the task object, the
object is closed before method execution.
-
- is specified in the connection string.
A
@@ -1236,8 +1223,6 @@ For more information about asynchronous programming in the .NET Framework Data P
Returned in the task object, the
object is closed before method execution.
-
- is specified in the connection string.
A
@@ -1298,8 +1283,6 @@ For more information about asynchronous programming in the .NET Framework Data P
Returned in the task object, the
object is closed before method execution.
-
- is specified in the connection string.
A
@@ -1372,8 +1355,6 @@ For more information about asynchronous programming in the .NET Framework Data P
Returned in the task object, the
object is closed before method execution.
-
- is specified in the connection string.
A
diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml
index 4dbe1f6511..523d339e97 100644
--- a/doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml
+++ b/doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml
@@ -284,12 +284,6 @@ The following console application creates updates data within the **AdventureWor
A timeout occurred during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/dotnet/framework/data/adonet/sqlclient-streaming-support).
- The name/value pair "Asynchronous Processing=true" was not included within the connection string defining the connection for this
-
- .
-
- -or-
-
The
closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/dotnet/framework/data/adonet/sqlclient-streaming-support).
@@ -403,12 +397,6 @@ To set up this example, create a new Windows application. Put a
- The name/value pair "Asynchronous Processing=true" was not included within the connection string defining the connection for this
-
- .
-
- -or-
-
The
closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/dotnet/framework/data/adonet/sqlclient-streaming-support).
@@ -487,12 +475,6 @@ The following console application starts the process of retrieving a data reader
A timeout occurred during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/dotnet/framework/data/adonet/sqlclient-streaming-support).
- The name/value pair "Asynchronous Processing=true" was not included within the connection string defining the connection for this
-
- .
-
- -or-
-
The
closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/dotnet/framework/data/adonet/sqlclient-streaming-support).
@@ -600,12 +582,6 @@ This example also passes the `CommandBehavior.CloseConnection` and `CommandBehav
A timeout occurred during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/dotnet/framework/data/adonet/sqlclient-streaming-support).
- The name/value pair "Asynchronous Processing=true" was not included within the connection string defining the connection for this
-
- .
-
- -or-
-
The
closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/dotnet/framework/data/adonet/sqlclient-streaming-support).
@@ -724,12 +700,6 @@ To set up this example, create a new Windows application. Put a
- The name/value pair "Asynchronous Processing=true" was not included within the connection string defining the connection for this
-
- .
-
- -or-
-
The
closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/dotnet/framework/data/adonet/sqlclient-streaming-support).
@@ -859,12 +829,6 @@ This example passes the `CommandBehavior.CloseConnection` value in the `behavior
A timeout occurred during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/dotnet/framework/data/adonet/sqlclient-streaming-support).
- The name/value pair "Asynchronous Processing=true" was not included within the connection string defining the connection for this
-
- .
-
- -or-
-
The
closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/dotnet/framework/data/adonet/sqlclient-streaming-support).
@@ -973,12 +937,6 @@ The following console application starts the process of retrieving XML data asyn
A timeout occurred during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/dotnet/framework/data/adonet/sqlclient-streaming-support).
- The name/value pair "Asynchronous Processing=true" was not included within the connection string defining the connection for this
-
- .
-
- -or-
-
The
closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/dotnet/framework/data/adonet/sqlclient-streaming-support).
@@ -1107,12 +1065,6 @@ To set up this example, create a new Windows application. Put a
- The name/value pair "Asynchronous Processing=true" was not included within the connection string defining the connection for this
-
- .
-
- -or-
-
The
closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/dotnet/framework/data/adonet/sqlclient-streaming-support).
@@ -1230,8 +1182,6 @@ A value of 0 indicates no limit (an attempt to execute a command will wait indef
> [!NOTE]
> The property will be ignored during old-style asynchronous method calls such as . It will be honored by the newer async methods such as .
- has no effect when the command is executed against a context connection (a opened with "context connection=true" in the connection string).
-
> [!NOTE]
> This property is the cumulative time-out (for all network packets that are read during the invocation of a method) for all network reads during command execution or processing of the results. A time-out can still occur after the first row is returned, and does not include user processing time, only network read time.
@@ -1725,10 +1675,6 @@ For more information about asynchronous programming in the .NET Framework Data P
The
closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/dotnet/framework/data/adonet/sqlclient-streaming-support).
-
- -or-
-
- is specified in the connection string.
SQL Server returned an error while executing the command text.
@@ -2022,10 +1968,6 @@ For more information about asynchronous programming in the .NET Framework Data P
The
closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/dotnet/framework/data/adonet/sqlclient-streaming-support).
-
- -or-
-
- is specified in the connection string.
SQL Server returned an error while executing the command text.
@@ -2124,10 +2066,6 @@ For more information about asynchronous programming in the .NET Framework Data P
-or-
closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/dotnet/framework/data/adonet/sqlclient-streaming-support).
-
- -or-
-
- is specified in the connection string.
SQL Server returned an error while executing the command text.
@@ -2227,10 +2165,6 @@ For more information about asynchronous programming in the .NET Framework Data P
The
closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/dotnet/framework/data/adonet/sqlclient-streaming-support).
-
- -or-
-
- is specified in the connection string.
SQL Server returned an error while executing the command text.
@@ -2334,10 +2268,6 @@ For more information about asynchronous programming in the .NET Framework Data P
The
closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/dotnet/framework/data/adonet/sqlclient-streaming-support).
-
- -or-
-
- is specified in the connection string.
SQL Server returned an error while executing the command text.
@@ -2513,10 +2443,6 @@ For more information about asynchronous programming in the .NET Framework Data P
The
closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/dotnet/framework/data/adonet/sqlclient-streaming-support).
-
- -or-
-
- is specified in the connection string.
SQL Server returned an error while executing the command text.
@@ -2708,10 +2634,6 @@ For more information about asynchronous programming in the .NET Framework Data P
The
closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/dotnet/framework/data/adonet/sqlclient-streaming-support).
-
- -or-
-
- is specified in the connection string.
SQL Server returned an error while executing the command text.
@@ -2806,10 +2728,6 @@ For more information about asynchronous programming in the .NET Framework Data P
The
closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/dotnet/framework/data/adonet/sqlclient-streaming-support).
-
- -or-
-
- is specified in the connection string.
SQL Server returned an error while executing the command text.
diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml
index 24aac534e4..3cc51f0f82 100644
--- a/doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml
+++ b/doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml
@@ -362,9 +362,6 @@ End Module
The connection string contains any combination of , , or .
--or-
-
-The connection string contains .
-or-
@@ -529,7 +526,7 @@ The connection string contains .
|App|N/A|Synonym of **Application Name**.|
|Application Name|N/A|The name of the application, or '.NET SQLClient Data Provider' if no application name is provided.
An application name can be 128 characters or less.|
|Application Intent
-or-
ApplicationIntent|ReadWrite|Declares the application workload type when connecting to a server. Possible values are `ReadOnly` and `ReadWrite`. For example:
`ApplicationIntent=ReadOnly`
For more information about SqlClient support for Always On Availability Groups, see [SqlClient Support for High Availability, Disaster Recovery](/dotnet/framework/data/adonet/sql/sqlclient-support-for-high-availability-disaster-recovery).|
-|Asynchronous Processing
-or-
Async|'false'|When `true`, enables asynchronous operation support. Recognized values are `true`, `false`, `yes`, and `no`.
This property is ignored beginning in .NET Framework 4.5. For more information about SqlClient support for asynchronous programming, see [Asynchronous Programming](/dotnet/framework/data/adonet/asynchronous-programming).|
+|Asynchronous Processing
-or-
Async|'false'|This property is obsolete and should not used.
When `true`, enables asynchronous operation support. Recognized values are `true`, `false`, `yes`, and `no`.
This property is ignored beginning in .NET Framework 4.5. For more information about SqlClient support for asynchronous programming, see [Asynchronous Programming](/dotnet/framework/data/adonet/asynchronous-programming).|
|Attestation Protocol|N/A|Gets or sets the value of Attestation Protocol.
Valid values are: `AAS` `HGS`|
|AttachDBFilename
-or-
Extended Properties
-or-
Initial File Name|N/A|The name of the primary database file, including the full path name of an attachable database. AttachDBFilename is only supported for primary data files with an .mdf extension.
If the value of the AttachDBFileName key is specified in the connection string, the database is attached and becomes the default database for the connection.
If this key is not specified and if the database was previously attached, the database will not be reattached. The previously attached database will be used as the default database for the connection.
If this key is specified together with the AttachDBFileName key, the value of this key will be used as the alias. However, if the name is already used in another attached database, the connection will fail.
The path may be absolute or relative by using the DataDirectory substitution string. If DataDirectory is used, the database file must exist within a subdirectory of the directory pointed to by the substitution string. **Note:** Remote server, HTTP, and UNC path names are not supported.
The database name must be specified with the keyword 'database' (or one of its aliases) as in the following:
An error will be generated if a log file exists in the same directory as the data file and the 'database' keyword is used when attaching the primary data file. In this case, remove the log file. Once the database is attached, a new log file will be automatically generated based on the physical path.|
|Authentication|N/A|The authentication method used for [Connecting to SQL Database By Using Azure Active Directory Authentication](https://azure.microsoft.com/documentation/articles/sql-database-aad-authentication/#7-connect-to-your-database-by-using-azure-active-directory-identities).
Valid values are:
`Active Directory Integrated`, `Active Directory Interactive`, `Active Directory Password`, `Sql Password`. Currently `Active Directory Integrated` and `Active Directory Interactive` modes of authentication are supported only for .NET Framework. |
@@ -539,7 +536,6 @@ The connection string contains .
|Connection Lifetime
-or-
Load Balance Timeout|0|When a connection is returned to the pool, its creation time is compared with the current time, and the connection is destroyed if that time span (in seconds) exceeds the value specified by `Connection Lifetime`. This is useful in clustered configurations to force load balancing between a running server and a server just brought online.
A value of zero (0) causes pooled connections to have the maximum connection timeout.|
|Connect Retry Count
-or-
ConnectRetryCount|1|Controls the number of reconnection attempts after the client identifies an idle connection failure. Valid values are 0 to 255. The default is 1. 0 means do not attempt to reconnect (disable connection resiliency).
For additional information about idle connection resiliency, see [Technical Article - Idle Connection Resiliency](https://go.microsoft.com/fwlink/?LinkId=393996).|
|Connect Retry Interval
-or-
ConnectRetryInterval|10|Specifies the time between each connection retry attempt (ConnectRetryCount). Valid values are 1 to 60 seconds (default=10), applied after the first reconnection attempt. When a broken connection is detected, the client immediately attempts to reconnect; this is the first reconnection attempt and only occurs if ConnectRetryCount is greater than 0. If the first reconnection attempt fails and ConnectRetryCount is greater than 1, the client waits ConnectRetryInterval to try the second and subsequent reconnection attempts.
For additional information about idle connection resiliency, see [Technical Article - Idle Connection Resiliency](https://go.microsoft.com/fwlink/?LinkId=393996).|
-|Context Connection|'false'|`true` if an in-process connection to SQL Server should be made.|
|Current Language
-or-
Language|N/A|Sets the language used for database server warning or error messages.
The language name can be 128 characters or less.|
|Data Source
-or-
Server
-or-
Address
-or-
Addr
-or-
Network Address|N/A|The name or network address of the instance of SQL Server to which to connect. The port number can be specified after the server name:
`server=tcp:servername, portnumber`
When specifying a local instance, always use (local). To force a protocol, add one of the following prefixes:
`np:(local), tcp:(local), lpc:(local)`
Beginning in .NET Framework 4.5, you can also connect to a LocalDB database as follows:
`server=(localdb)\\myInstance`
For more information about LocalDB, see [SqlClient Support for LocalDB](/dotnet/framework/data/adonet/sql/sqlclient-support-for-localdb).
**Data Source** must use the TCP format or the Named Pipes format.
TCP format is as follows:
- tcp:\\\ - tcp:\,\
The TCP format must start with the prefix "tcp:" and is followed by the database instance, as specified by a host name and an instance name. This format is not applicable when connecting to Azure SQL Database. TCP is automatically selected for connections to Azure SQL Database when no protocol is specified.
The host name MUST be specified in one of the following ways:
- NetBIOSName - IPv4Address - IPv6Address
The instance name is used to resolve to a particular TCP/IP port number on which a database instance is hosted. Alternatively, specifying a TCP/IP port number directly is also allowed. If both instance name and port number are not present, the default database instance is used.
The Named Pipes format is as follows:
- np:\\\\\pipe\\
The Named Pipes format MUST start with the prefix "np:" and is followed by a named pipe name.
The host name MUST be specified in one of the following ways:
- NetBIOSName - IPv4Address - IPv6Address
The pipe name is used to identify the database instance to which the .NET Framework application will be connected.
If the value of the **Network** key is specified, the prefixes "tcp:" and "np:" should not be specified. **Note:** You can force the use of TCP instead of shared memory, either by prefixing **tcp:** to the server name in the connection string, or by using **localhost**.|
|Enclave Attestation Url|N/A|Gets or sets the enclave attestation Url to be used with enclave based Always Encrypted.|
@@ -652,8 +648,6 @@ The connection string contains .
- If is set on an open connection.
-- If is set when `Context Connection=true`.
-
- If is set when `Integrated Security = true`.
- If is set when the connection string uses `Password`.
@@ -692,14 +686,7 @@ The connection string contains .
The name of the instance of SQL Server to which to connect. The default value is an empty string. [!NOTE]
-> The property returns `null` if the connection string for the is "context connection=true".
-
-
-
+
## Examples
The following example creates a and displays some of its read-only properties.
@@ -1007,8 +994,6 @@ GO
Calling more than once for the same instance before task completion.
- is specified in the connection string.
-
A connection was not available from the connection pool before the connection time out elapsed.Any error returned by SQL Server that occurred while opening the connection.
diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionStringBuilder.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionStringBuilder.xml
index 98d4d5cc70..5d3deb30b7 100644
--- a/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionStringBuilder.xml
+++ b/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionStringBuilder.xml
@@ -120,21 +120,14 @@ Modified: Data Source=(local);Initial Catalog=AdventureWorks;Integrated Security
To set the value to null, use .
- Gets or sets a Boolean value that indicates whether asynchronous processing is allowed by the connection created by using this connection string.
+ Obsolete. Gets or sets a Boolean value that indicates whether asynchronous processing is allowed by the connection created by using this connection string.The value of the property, or if no value has been supplied. object, this key/value pair must be included within the connection string of the associated object.
-
-
-
-## Examples
- The following example retrieves a connection string and verifies that the connection string is configured to allow for asynchronous processing. (In this case, the string comes from a procedure within the application, but in a production application, the connection string might come from a configuration file, or some other source.) Then, the example performs an asynchronous operation, updating values within a sample database on a background thread.
-
- [!code-csharp[SqlConnectionStringBuilder_AsynchronousProcessing#1](~/../sqlclient/doc/samples/SqlConnectionStringBuilder_AsynchronousProcessing.cs#1)]
-
+
]]>
@@ -306,7 +299,7 @@ False
is null ( in Visual Basic)
- Gets or sets a value that indicates whether a client/server or in-process connection to SQL Server should be made.
+ Obsolete. Gets or sets a value that indicates whether a client/server or in-process connection to SQL Server should be made.The value of the property, or if none has been supplied.:
```
diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlDataReader.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlDataReader.xml
index 9f61a25a03..f4459bdda9 100644
--- a/doc/snippets/Microsoft.Data.SqlClient/SqlDataReader.xml
+++ b/doc/snippets/Microsoft.Data.SqlClient/SqlDataReader.xml
@@ -386,9 +386,7 @@
Tried to read a previously-read column in sequential mode.
- There was an asynchronous operation in progress. This applies to all Get* methods when running in sequential mode, as they could be called while reading a stream.
-
- is specified in the connection string.
+ There was an asynchronous operation in progress. This applies to all Get* methods when running in sequential mode, as they could be called while reading a stream.Trying to read a column that does not exist.The value of the column was null ( == ), retrieving a non-SQL type.
@@ -835,8 +833,6 @@
- WriteTimeout
- When the connection property `ContextConnection=true`, only supports synchronous data retrieval for both sequential () and non-sequential () access.
-
For more information, see [SqlClient Streaming Support](/dotnet/framework/data/adonet/sqlclient-streaming-support).
]]>
@@ -891,8 +887,6 @@
will raise an exception when used on an object returned by when is in effect.
- When the connection property `ContextConnection=true`, only supports synchronous data retrieval for both sequential () and non-sequential () access.
-
For more information, see [SqlClient Streaming Support](/dotnet/framework/data/adonet/sqlclient-streaming-support).
]]>
@@ -1077,9 +1071,8 @@
Trying to read a previously read column in sequential mode.
- There was an asynchronous operation in progress. This applies to all Get* methods when running in sequential mode, as they could be called while reading a stream.
-
- is specified in the connection string.
+ There was an asynchronous operation in progress. This applies to all Get* methods when running in sequential mode, as they could be called while reading a stream.
+
Trying to read a column that does not exist.
@@ -1137,9 +1130,7 @@
]]>
- Calling more than once for the same instance before task completion.
-
- is specified in the connection string.
+ Calling more than once for the same instance before task completion.SQL Server returned an error while executing the command text.
@@ -1181,9 +1172,7 @@
]]>
- Calling more than once for the same instance before task completion.
-
- is specified in the connection string.
+ Calling more than once for the same instance before task completion.SQL Server returned an error while executing the command text.
diff --git a/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs b/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs
index 9192733060..685d52b421 100644
--- a/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs
+++ b/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs
@@ -909,6 +909,7 @@ public SqlConnectionStringBuilder(string connectionString) { }
///
[System.ComponentModel.DisplayNameAttribute("Asynchronous Processing")]
[System.ComponentModel.RefreshPropertiesAttribute(System.ComponentModel.RefreshProperties.All)]
+ [System.ObsoleteAttribute("AsynchronousProcessing has been deprecated. SqlConnection will ignore the 'Asynchronous Processing' keyword and always allow asynchronous processing.")]
public bool AsynchronousProcessing { get { throw null; } set { } }
///
[System.ComponentModel.DisplayNameAttribute("AttachDbFilename")]
@@ -931,7 +932,7 @@ public SqlConnectionStringBuilder(string connectionString) { }
[System.ComponentModel.BrowsableAttribute(false)]
[System.ComponentModel.DisplayNameAttribute("Connection Reset")]
[System.ComponentModel.RefreshPropertiesAttribute(System.ComponentModel.RefreshProperties.All)]
- [System.ObsoleteAttribute("ConnectionReset has been deprecated. SqlConnection will ignore the 'connection reset' keyword and always reset the connection")]
+ [System.ObsoleteAttribute("ConnectionReset has been deprecated. SqlConnection will ignore the 'connection reset' keyword and always reset the connection.")]
public bool ConnectionReset { get { throw null; } set { } }
///
[System.ComponentModel.DisplayNameAttribute("Connect Retry Count")]
@@ -948,6 +949,7 @@ public SqlConnectionStringBuilder(string connectionString) { }
///
[System.ComponentModel.DisplayNameAttribute("Context Connection")]
[System.ComponentModel.RefreshPropertiesAttribute(System.ComponentModel.RefreshProperties.All)]
+ [System.ObsoleteAttribute("ContextConnection has been deprecated. SqlConnection will ignore the 'Context Connection' keyword.")]
public bool ContextConnection { get { throw null; } set { } }
///
[System.ComponentModel.DisplayNameAttribute("Current Language")]
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnectionStringBuilder.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnectionStringBuilder.cs
index 9b44f7459a..17d62e41bd 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnectionStringBuilder.cs
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnectionStringBuilder.cs
@@ -362,9 +362,11 @@ public override object this[string keyword]
Certificate = ConvertToString(value);
break;
#endif
+#pragma warning disable 618 // Obsolete AsynchronousProcessing
case Keywords.AsynchronousProcessing:
AsynchronousProcessing = ConvertToBoolean(value);
break;
+#pragma warning restore 618
case Keywords.PoolBlockingPeriod:
PoolBlockingPeriod = ConvertToPoolBlockingPeriod(keyword, value);
break;
@@ -372,10 +374,11 @@ public override object this[string keyword]
case Keywords.ConnectionReset:
ConnectionReset = ConvertToBoolean(value);
break;
-#pragma warning restore 618
+ // Obsolete ContextConnection
case Keywords.ContextConnection:
ContextConnection = ConvertToBoolean(value);
break;
+#pragma warning restore 618
case Keywords.Encrypt:
Encrypt = ConvertToBoolean(value);
break;
@@ -462,6 +465,7 @@ public string ApplicationName
///
[DisplayName(DbConnectionStringKeywords.AsynchronousProcessing)]
+ [Obsolete("AsynchronousProcessing has been deprecated. SqlConnection will ignore the 'Asynchronous Processing' keyword and always allow asynchronous processing.")]
[ResCategoryAttribute(StringsHelper.ResourceNames.DataCategory_Initialization)]
[ResDescriptionAttribute(StringsHelper.ResourceNames.DbConnectionString_AsynchronousProcessing)]
[RefreshPropertiesAttribute(RefreshProperties.All)]
@@ -534,7 +538,7 @@ public int CommandTimeout
///
[Browsable(false)]
[DisplayName(DbConnectionStringKeywords.ConnectionReset)]
- [Obsolete("ConnectionReset has been deprecated. SqlConnection will ignore the 'connection reset' keyword and always reset the connection")] // SQLPT 41700
+ [Obsolete("ConnectionReset has been deprecated. SqlConnection will ignore the 'connection reset' keyword and always reset the connection.")] // SQLPT 41700
[ResCategoryAttribute(StringsHelper.ResourceNames.DataCategory_Pooling)]
[ResDescriptionAttribute(StringsHelper.ResourceNames.DbConnectionString_ConnectionReset)]
[RefreshPropertiesAttribute(RefreshProperties.All)]
@@ -550,6 +554,7 @@ public bool ConnectionReset
///
[DisplayName(DbConnectionStringKeywords.ContextConnection)]
+ [Obsolete("ContextConnection has been deprecated. SqlConnection will ignore the 'Context Connection' keyword.")]
[ResCategoryAttribute(StringsHelper.ResourceNames.DataCategory_Source)]
[ResDescriptionAttribute(StringsHelper.ResourceNames.DbConnectionString_ContextConnection)]
[RefreshPropertiesAttribute(RefreshProperties.All)]
@@ -1270,8 +1275,10 @@ private object GetAt(Keywords index)
return this.ApplicationIntent;
case Keywords.ApplicationName:
return ApplicationName;
+#pragma warning disable 618 // Obsolete AsynchronousProcessing
case Keywords.AsynchronousProcessing:
return AsynchronousProcessing;
+#pragma warning restore 618
case Keywords.AttachDBFilename:
return AttachDBFilename;
case Keywords.PoolBlockingPeriod:
@@ -1283,9 +1290,10 @@ private object GetAt(Keywords index)
#pragma warning disable 618 // Obsolete ConnectionReset
case Keywords.ConnectionReset:
return ConnectionReset;
-#pragma warning restore 618
+ // Obsolete ConnectionReset
case Keywords.ContextConnection:
return ContextConnection;
+#pragma warning restore 618
case Keywords.CurrentLanguage:
return CurrentLanguage;
case Keywords.DataSource:
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlDependencyListener.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlDependencyListener.cs
index d05a0bb2b2..0f00a3ffdb 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlDependencyListener.cs
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlDependencyListener.cs
@@ -1536,7 +1536,9 @@ private static SqlConnectionContainerHashHelper GetHashHelper(string connectionS
// This logic is done here to enable us to have the complete connection string now to be used
// for tracing as we flow through the logic.
connectionStringBuilder = new SqlConnectionStringBuilder(connectionString);
+#pragma warning disable CS0618 // Obsolete AsynchronousProcessing
connectionStringBuilder.AsynchronousProcessing = true;
+#pragma warning restore CS0618
connectionStringBuilder.Pooling = false;
connectionStringBuilder.Enlist = false;
connectionStringBuilder.ConnectRetryCount = 0;
From 699ae37a2ba193c16f653b13400c990249d94569 Mon Sep 17 00:00:00 2001
From: Karina Zhou
Date: Fri, 11 Dec 2020 12:51:55 -0800
Subject: [PATCH 010/509] Fix Kerberos Authentication (#845)
---
.../System.Net.Security.Native/Interop.NetSecurityNative.cs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Unix/System.Net.Security.Native/Interop.NetSecurityNative.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Unix/System.Net.Security.Native/Interop.NetSecurityNative.cs
index e3e3e3759b..ab8338e796 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Unix/System.Net.Security.Native/Interop.NetSecurityNative.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Unix/System.Net.Security.Native/Interop.NetSecurityNative.cs
@@ -28,14 +28,14 @@ internal static extern Status DisplayMajorStatus(
Status statusValue,
ref GssBuffer buffer);
- [DllImport(Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_ImportUserName", CharSet = CharSet.Unicode)]
+ [DllImport(Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_ImportUserName")]
internal static extern Status ImportUserName(
out Status minorStatus,
string inputName,
int inputNameByteCount,
out SafeGssNameHandle outputName);
- [DllImport(Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_ImportPrincipalName", CharSet = CharSet.Unicode)]
+ [DllImport(Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_ImportPrincipalName")]
internal static extern Status ImportPrincipalName(
out Status minorStatus,
string inputName,
@@ -53,7 +53,7 @@ internal static extern Status InitiateCredSpNego(
SafeGssNameHandle desiredName,
out SafeGssCredHandle outputCredHandle);
- [DllImport(Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_InitiateCredWithPassword", CharSet = CharSet.Unicode)]
+ [DllImport(Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_InitiateCredWithPassword")]
internal static extern Status InitiateCredWithPassword(
out Status minorStatus,
bool isNtlm,
From 83e2c645f0798351b5b7aad944809b5f77cf185c Mon Sep 17 00:00:00 2001
From: Cheena Malhotra
Date: Fri, 18 Dec 2020 13:36:25 -0800
Subject: [PATCH 011/509] Fix | Fix TCP Keep Alive missing call (#854)
---
.../netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs
index ef85841d24..51932e9c95 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs
@@ -364,6 +364,10 @@ void Cancel()
if (ipAddresses[i] != null)
{
sockets[i] = new Socket(ipAddresses[i].AddressFamily, SocketType.Stream, ProtocolType.Tcp);
+
+ // enable keep-alive on socket
+ SetKeepAliveValues(ref sockets[i]);
+
sockets[i].Connect(ipAddresses[i], port);
if (sockets[i] != null) // sockets[i] can be null if cancel callback is executed during connect()
{
From 21b0197c0d08cb1e9237eb599cb3135e5a936ff7 Mon Sep 17 00:00:00 2001
From: Cheena Malhotra
Date: Fri, 18 Dec 2020 15:44:40 -0800
Subject: [PATCH 012/509] Update release notes for v2.1.1 (#856)
---
CHANGELOG.md | 8 ++++
release-notes/2.1/2.1.1.md | 75 +++++++++++++++++++++++++++++++++++++
release-notes/2.1/2.1.md | 1 +
release-notes/2.1/README.md | 1 +
4 files changed, 85 insertions(+)
create mode 100644 release-notes/2.1/2.1.1.md
diff --git a/CHANGELOG.md b/CHANGELOG.md
index dceaa7c412..f40264b6e5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
+## [Stable Release 2.1.1] - 2020-12-18
+
+### Fixed
+- Fixed issue with System-Assigned Managed Identity in Azure Functions [#841](https://github.com/dotnet/SqlClient/pull/841)
+- Fixed issue with Kerberos Authentication for .NET Core in Unix environments [#848](https://github.com/dotnet/SqlClient/pull/848)
+- Fixed issue with TCP Keep Alive for .NET Core in Unix environments [#855](https://github.com/dotnet/SqlClient/pull/855)
+
+
## [Stable Release 2.1.0] - 2020-11-19
### Added
diff --git a/release-notes/2.1/2.1.1.md b/release-notes/2.1/2.1.1.md
new file mode 100644
index 0000000000..35de2ed583
--- /dev/null
+++ b/release-notes/2.1/2.1.1.md
@@ -0,0 +1,75 @@
+# Release Notes
+
+## Microsoft.Data.SqlClient 2.1.1 released 18 December 2020
+
+This update brings the below changes over the previous stable release:
+
+### Fixed
+- Fixed issue with System-Assigned Managed Identity in Azure Functions [#841](https://github.com/dotnet/SqlClient/pull/841)
+- Fixed issue with Kerberos Authentication for .NET Core in Unix environments [#848](https://github.com/dotnet/SqlClient/pull/848)
+- Fixed issue with TCP Keep Alive for .NET Core in Unix environments [#855](https://github.com/dotnet/SqlClient/pull/855)
+
+### Target Platform Support
+
+- .NET Framework 4.6+ (Windows x86, Windows x64)
+- .NET Core 2.1+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS)
+- .NET Standard 2.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS)
+
+### Dependencies
+
+#### .NET Framework
+
+- Microsoft.Data.SqlClient.SNI 2.1.1
+- Microsoft.Identity.Client 4.21.1
+- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.8.0
+- Microsoft.IdentityModel.JsonWebTokens 6.8.0
+
+#### .NET Core 2.1
+
+- Microsoft.Data.SqlClient.SNI.runtime 2.1.1
+- Microsoft.Win32.Registry 4.7.0
+- System.Security.Principal.Windows 4.7.0
+- System.Text.Encoding.CodePages 4.7.0
+- System.Diagnostics.DiagnosticSource 4.7.0
+- System.Configuration.ConfigurationManager 4.7.0
+- System.Runtime.Caching 4.7.0
+- Microsoft.Identity.Client 4.21.1
+- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.8.0
+- Microsoft.IdentityModel.JsonWebTokens 6.8.0
+
+#### .NET Core 3.1
+
+- Microsoft.Data.SqlClient.SNI.runtime 2.1.1
+- Microsoft.Win32.Registry 4.7.0
+- System.Security.Principal.Windows 4.7.0
+- System.Text.Encoding.CodePages 4.7.0
+- System.Diagnostics.DiagnosticSource 4.7.0
+- System.Configuration.ConfigurationManager 4.7.0
+- System.Runtime.Caching 4.7.0
+- Microsoft.Identity.Client 4.21.1
+- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.8.0
+- Microsoft.IdentityModel.JsonWebTokens 6.8.0
+
+#### .NET Standard 2.0
+
+- Microsoft.Data.SqlClient.SNI.runtime 2.1.1
+- Microsoft.Win32.Registry 4.7.0
+- System.Buffers 4.5.1
+- System.Memory 4.5.4
+- System.Security.Principal.Windows 4.7.0
+- System.Text.Encoding.CodePages 4.7.0
+- Microsoft.Identity.Client 4.21.1
+- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.8.0
+- Microsoft.IdentityModel.JsonWebTokens 6.8.0
+
+#### .NET Standard 2.1
+
+- Microsoft.Data.SqlClient.SNI.runtime 2.1.1
+- Microsoft.Win32.Registry 4.7.0
+- System.Buffers 4.5.1
+- System.Memory 4.5.4
+- System.Security.Principal.Windows 4.7.0
+- System.Text.Encoding.CodePages 4.7.0
+- Microsoft.Identity.Client 4.21.1
+- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.8.0
+- Microsoft.IdentityModel.JsonWebTokens 6.8.0
diff --git a/release-notes/2.1/2.1.md b/release-notes/2.1/2.1.md
index 1be1be4fb0..f877ee5ae2 100644
--- a/release-notes/2.1/2.1.md
+++ b/release-notes/2.1/2.1.md
@@ -4,6 +4,7 @@ The following Microsoft.Data.SqlClient 2.1 stable releases have been shipped:
| Release Date | Version | Notes |
| :-- | :-- | :--: |
+| 2020/12/18 | 2.1.1 | [release notes](2.1.1.md) |
| 2020/11/19 | 2.1.0 | [release notes](2.1.0.md) |
The following Microsoft.Data.SqlClient 2.1 preview releases have been shipped:
diff --git a/release-notes/2.1/README.md b/release-notes/2.1/README.md
index 1be1be4fb0..f877ee5ae2 100644
--- a/release-notes/2.1/README.md
+++ b/release-notes/2.1/README.md
@@ -4,6 +4,7 @@ The following Microsoft.Data.SqlClient 2.1 stable releases have been shipped:
| Release Date | Version | Notes |
| :-- | :-- | :--: |
+| 2020/12/18 | 2.1.1 | [release notes](2.1.1.md) |
| 2020/11/19 | 2.1.0 | [release notes](2.1.0.md) |
The following Microsoft.Data.SqlClient 2.1 preview releases have been shipped:
From a9c21bbd1a321f4314eb256e0b1a7e7a6f0d8aba Mon Sep 17 00:00:00 2001
From: Wraith
Date: Tue, 22 Dec 2020 16:31:02 +0000
Subject: [PATCH 013/509] Share more files and add MultiPartIdentifier tests
(#827)
---
.../src/Microsoft.Data.SqlClient.csproj | 12 +-
.../src/Microsoft/Data/Common/DataStorage.cs | 531 ------------------
.../Data/Common/DbConnectionPoolKey.cs | 59 --
.../Data/Common/MultipartIdentifier.cs | 293 ----------
.../netfx/src/Microsoft.Data.SqlClient.csproj | 10 +-
.../Data/Common/DbConnectionPoolKey.cs | 0
.../Data/Common/MultipartIdentifier.cs | 0
.../Microsoft.Data.SqlClient.Tests.csproj | 2 +
.../MultipartIdentifierTests.cs | 260 +++++++++
9 files changed, 275 insertions(+), 892 deletions(-)
delete mode 100644 src/Microsoft.Data.SqlClient/netfx/src/Common/src/Microsoft/Data/Common/DataStorage.cs
delete mode 100644 src/Microsoft.Data.SqlClient/netfx/src/Common/src/Microsoft/Data/Common/DbConnectionPoolKey.cs
delete mode 100644 src/Microsoft.Data.SqlClient/netfx/src/Common/src/Microsoft/Data/Common/MultipartIdentifier.cs
rename src/Microsoft.Data.SqlClient/{netcore/src/Common => }/src/Microsoft/Data/Common/DbConnectionPoolKey.cs (100%)
rename src/Microsoft.Data.SqlClient/{netcore/src/Common => }/src/Microsoft/Data/Common/MultipartIdentifier.cs (100%)
create mode 100644 src/Microsoft.Data.SqlClient/tests/FunctionalTests/MultipartIdentifierTests.cs
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
index e46d123395..5a299ba2e1 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
@@ -51,6 +51,12 @@
Microsoft\Data\Common\ActivityCorrelator.cs
+
+ Microsoft\Data\Common\DbConnectionPoolKey.cs
+
+
+ Microsoft\Data\Common\MultipartIdentifier.cs
+
Microsoft\Data\SqlClient\DataClassification\SensitivityClassification.cs
@@ -321,9 +327,6 @@
Microsoft\Data\Common\DbConnectionOptions.Common.cs
-
- Microsoft\Data\Common\DbConnectionPoolKey.cs
-
Microsoft\Data\Common\FieldNameLookup.cs
@@ -331,9 +334,6 @@
Microsoft\Data\Common\BasicFieldNameLookup.cs
-
- Microsoft\Data\Common\MultipartIdentifier.cs
-
Microsoft\Data\Common\NameValuePair.cs
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Common/src/Microsoft/Data/Common/DataStorage.cs b/src/Microsoft.Data.SqlClient/netfx/src/Common/src/Microsoft/Data/Common/DataStorage.cs
deleted file mode 100644
index 713ddcffb6..0000000000
--- a/src/Microsoft.Data.SqlClient/netfx/src/Common/src/Microsoft/Data/Common/DataStorage.cs
+++ /dev/null
@@ -1,531 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace Microsoft.Data.Common {
- using System;
- using System.Collections;
- using System.Collections.Concurrent;
- using System.Collections.Generic;
- using Microsoft.Data.SqlTypes;
- using System.Diagnostics;
- using System.Xml;
- using System.Xml.Serialization;
- using System.Data.SqlTypes;
- using System.Data;
-
- internal enum StorageType {
- Empty = TypeCode.Empty, // 0
- Object = TypeCode.Object,
- DBNull = TypeCode.DBNull,
- Boolean = TypeCode.Boolean,
- Char = TypeCode.Char,
- SByte = TypeCode.SByte,
- Byte = TypeCode.Byte,
- Int16 = TypeCode.Int16,
- UInt16 = TypeCode.UInt16,
- Int32 = TypeCode.Int32,
- UInt32 = TypeCode.UInt32,
- Int64 = TypeCode.Int64,
- UInt64 = TypeCode.UInt64,
- Single = TypeCode.Single,
- Double = TypeCode.Double,
- Decimal = TypeCode.Decimal, // 15
- DateTime = TypeCode.DateTime, // 16
- TimeSpan = 17,
- String = TypeCode.String, // 18
- Guid = 19,
-
- ByteArray = 20,
- CharArray = 21,
- Type = 22,
- DateTimeOffset = 23,
- BigInteger = 24,
- Uri = 25,
-
- SqlBinary, // SqlTypes should remain at the end for IsSqlType checking
- SqlBoolean,
- SqlByte,
- SqlBytes,
- SqlChars,
- SqlDateTime,
- SqlDecimal,
- SqlDouble,
- SqlGuid,
- SqlInt16,
- SqlInt32,
- SqlInt64,
- SqlMoney,
- SqlSingle,
- SqlString,
-// SqlXml,
- };
-
- abstract internal class DataStorage {
-
- // for Whidbey 40426, searching down the Type[] is about 20% faster than using a Dictionary
- // must keep in same order as enum StorageType
- private static readonly Type[] StorageClassType = new Type[] {
- null,
- typeof(Object),
- typeof(DBNull),
- typeof(Boolean),
- typeof(Char),
- typeof(SByte),
- typeof(Byte),
- typeof(Int16),
- typeof(UInt16),
- typeof(Int32),
- typeof(UInt32),
- typeof(Int64),
- typeof(UInt64),
- typeof(Single),
- typeof(Double),
- typeof(Decimal),
- typeof(DateTime),
- typeof(TimeSpan),
- typeof(String),
- typeof(Guid),
-
- typeof(byte[]),
- typeof(char[]),
- typeof(Type),
- typeof(DateTimeOffset),
- typeof(System.Numerics.BigInteger),
- typeof(Uri),
-
- typeof(SqlBinary),
- typeof(SqlBoolean),
- typeof(SqlByte),
- typeof(SqlBytes),
- typeof(SqlChars),
- typeof(SqlDateTime),
- typeof(SqlDecimal),
- typeof(SqlDouble),
- typeof(SqlGuid),
- typeof(SqlInt16),
- typeof(SqlInt32),
- typeof(SqlInt64),
- typeof(SqlMoney),
- typeof(SqlSingle),
- typeof(SqlString),
-// typeof(SqlXml),
- };
-
- internal readonly DataColumn Column;
- internal readonly DataTable Table;
- internal readonly Type DataType;
- internal readonly StorageType StorageTypeCode;
- private System.Collections.BitArray dbNullBits;
-
- private readonly object DefaultValue;
- internal readonly object NullValue;
-
- internal readonly bool IsCloneable;
- internal readonly bool IsCustomDefinedType;
- internal readonly bool IsStringType;
- internal readonly bool IsValueType;
-
- private readonly static Func> _inspectTypeForInterfaces = InspectTypeForInterfaces;
- private readonly static ConcurrentDictionary> _typeImplementsInterface = new ConcurrentDictionary>();
-
- protected DataStorage(DataColumn column, Type type, object defaultValue, StorageType storageType)
- : this(column, type, defaultValue, DBNull.Value, false, storageType) {
- }
-
- protected DataStorage(DataColumn column, Type type, object defaultValue, object nullValue, StorageType storageType)
- : this(column, type, defaultValue, nullValue, false, storageType) {
- }
-
- protected DataStorage(DataColumn column, Type type, object defaultValue, object nullValue, bool isICloneable, StorageType storageType) {
- Debug.Assert(storageType == GetStorageType(type), "Incorrect storage type specified");
- Column = column;
- Table = column.Table;
- DataType = type;
- StorageTypeCode = storageType;
- DefaultValue = defaultValue;
- NullValue = nullValue;
- IsCloneable = isICloneable;
- IsCustomDefinedType = IsTypeCustomType(StorageTypeCode);
- IsStringType = ((StorageType.String == StorageTypeCode) || (StorageType.SqlString == StorageTypeCode));
- IsValueType = DetermineIfValueType(StorageTypeCode, type);
- }
-
- internal DataSetDateTime DateTimeMode {
- get {
- return Column.DateTimeMode;
- }
- }
-
- internal IFormatProvider FormatProvider {
- get {
- return Table.FormatProvider;
- }
- }
-
- public virtual Object Aggregate(int[] recordNos, AggregateType kind) {
- if (AggregateType.Count == kind) {
- return this.AggregateCount(recordNos);
- }
- return null;
- }
-
- public object AggregateCount(int[] recordNos) {
- int count = 0;
- for (int i = 0; i < recordNos.Length; i++) {
- if (!this.dbNullBits.Get(recordNos[i]))
- count++;
- }
- return count;
- }
-
- protected int CompareBits(int recordNo1, int recordNo2) {
- bool recordNo1Null = this.dbNullBits.Get(recordNo1);
- bool recordNo2Null = this.dbNullBits.Get(recordNo2);
- if (recordNo1Null ^ recordNo2Null) {
- if (recordNo1Null)
- return -1;
- else
- return 1;
- }
-
- return 0;
- }
-
- public abstract int Compare(int recordNo1, int recordNo2);
-
- // only does comparision, expect value to be of the correct type
- public abstract int CompareValueTo(int recordNo1, object value);
-
- // only does conversion with support for reference null
- public virtual object ConvertValue(object value) {
- return value;
- }
-
- protected void CopyBits(int srcRecordNo, int dstRecordNo) {
- this.dbNullBits.Set(dstRecordNo, this.dbNullBits.Get(srcRecordNo));
- }
-
- abstract public void Copy(int recordNo1, int recordNo2);
-
- abstract public Object Get(int recordNo);
-
- protected Object GetBits(int recordNo) {
- if (this.dbNullBits.Get(recordNo)) {
- return NullValue;
- }
- return DefaultValue;
- }
-
- virtual public int GetStringLength(int record) {
- System.Diagnostics.Debug.Assert(false, "not a String or SqlString column");
- return Int32.MaxValue;
- }
-
- protected bool HasValue(int recordNo) {
- return !this.dbNullBits.Get(recordNo);
- }
-
- public virtual bool IsNull(int recordNo) {
- return this.dbNullBits.Get(recordNo);
- }
-
- // convert (may not support reference null) and store the value
- abstract public void Set(int recordNo, Object value);
-
- protected void SetNullBit(int recordNo, bool flag) {
- this.dbNullBits.Set(recordNo, flag);
- }
-
- virtual public void SetCapacity(int capacity) {
- if (null == this.dbNullBits) {
- this.dbNullBits = new BitArray(capacity);
- }
- else {
- this.dbNullBits.Length = capacity;
- }
- }
-
- abstract public object ConvertXmlToObject(string s);
- public virtual object ConvertXmlToObject(XmlReader xmlReader, XmlRootAttribute xmlAttrib) {
- return ConvertXmlToObject(xmlReader.Value);
- }
-
- abstract public string ConvertObjectToXml(object value);
- public virtual void ConvertObjectToXml(object value, XmlWriter xmlWriter, XmlRootAttribute xmlAttrib) {
- xmlWriter.WriteString(ConvertObjectToXml(value));// should it be NO OP?
- }
-
- public static DataStorage CreateStorage(DataColumn column, Type dataType, StorageType typeCode) {
- Debug.Assert(typeCode == GetStorageType(dataType), "Incorrect storage type specified");
- if ((StorageType.Empty == typeCode) && (null != dataType)) {
- if (typeof(INullable).IsAssignableFrom(dataType)) { // Udt, OracleTypes
- return new SqlUdtStorage(column, dataType);
- }
- else {
- return new ObjectStorage(column, dataType); // non-nullable non-primitives
- }
- }
-
- switch (typeCode) {
- case StorageType.Empty: throw ExceptionBuilder.InvalidStorageType(TypeCode.Empty);
- case StorageType.DBNull: throw ExceptionBuilder.InvalidStorageType(TypeCode.DBNull);
- case StorageType.Object: return new ObjectStorage(column, dataType);
- case StorageType.Boolean: return new BooleanStorage(column);
- case StorageType.Char: return new CharStorage(column);
- case StorageType.SByte: return new SByteStorage(column);
- case StorageType.Byte: return new ByteStorage(column);
- case StorageType.Int16: return new Int16Storage(column);
- case StorageType.UInt16: return new UInt16Storage(column);
- case StorageType.Int32: return new Int32Storage(column);
- case StorageType.UInt32: return new UInt32Storage(column);
- case StorageType.Int64: return new Int64Storage(column);
- case StorageType.UInt64: return new UInt64Storage(column);
- case StorageType.Single: return new SingleStorage(column);
- case StorageType.Double: return new DoubleStorage(column);
- case StorageType.Decimal: return new DecimalStorage(column);
- case StorageType.DateTime: return new DateTimeStorage(column);
- case StorageType.TimeSpan: return new TimeSpanStorage(column);
- case StorageType.String: return new StringStorage(column);
- case StorageType.Guid: return new ObjectStorage(column, dataType);
-
- case StorageType.ByteArray: return new ObjectStorage(column, dataType);
- case StorageType.CharArray: return new ObjectStorage(column, dataType);
- case StorageType.Type: return new ObjectStorage(column, dataType);
- case StorageType.DateTimeOffset: return new DateTimeOffsetStorage(column);
- case StorageType.BigInteger: return new BigIntegerStorage(column);
- case StorageType.Uri: return new ObjectStorage(column, dataType);
-
- case StorageType.SqlBinary: return new SqlBinaryStorage(column);
- case StorageType.SqlBoolean: return new SqlBooleanStorage(column);
- case StorageType.SqlByte: return new SqlByteStorage(column);
- case StorageType.SqlBytes: return new SqlBytesStorage(column);
- case StorageType.SqlChars: return new SqlCharsStorage(column);
- case StorageType.SqlDateTime: return new SqlDateTimeStorage(column); //???/ what to do
- case StorageType.SqlDecimal: return new SqlDecimalStorage(column);
- case StorageType.SqlDouble: return new SqlDoubleStorage(column);
- case StorageType.SqlGuid: return new SqlGuidStorage(column);
- case StorageType.SqlInt16: return new SqlInt16Storage(column);
- case StorageType.SqlInt32: return new SqlInt32Storage(column);
- case StorageType.SqlInt64: return new SqlInt64Storage(column);
- case StorageType.SqlMoney: return new SqlMoneyStorage(column);
- case StorageType.SqlSingle: return new SqlSingleStorage(column);
- case StorageType.SqlString: return new SqlStringStorage(column);
- // case StorageType.SqlXml: return new SqlXmlStorage(column);
-
- default:
- System.Diagnostics.Debug.Assert(false, "shouldn't be here");
- goto case StorageType.Object;
- }
- }
-
- internal static StorageType GetStorageType(Type dataType) {
- for (int i = 0; i < StorageClassType.Length; ++i) {
- if (dataType == StorageClassType[i]) {
- return (StorageType)i;
- }
- }
- TypeCode tcode = Type.GetTypeCode(dataType);
- if (TypeCode.Object != tcode) { // enum -> Int64/Int32/Int16/Byte
- return (StorageType)tcode;
- }
- return StorageType.Empty;
- }
-
- internal static Type GetTypeStorage(StorageType storageType) {
- return StorageClassType[(int)storageType];
- }
-
- internal static bool IsTypeCustomType(Type type) {
- return IsTypeCustomType(GetStorageType(type));
- }
-
- internal static bool IsTypeCustomType(StorageType typeCode) {
- return ((StorageType.Object == typeCode) || (StorageType.Empty == typeCode) || (StorageType.CharArray == typeCode));
- }
-
- internal static bool IsSqlType(StorageType storageType) {
- return (StorageType.SqlBinary <= storageType);
- }
-
- public static bool IsSqlType(Type dataType) {
- for (int i = (int)StorageType.SqlBinary; i < StorageClassType.Length; ++i) {
- if (dataType == StorageClassType[i]) {
- return true;
- }
- }
- return false;
- }
-
- private static bool DetermineIfValueType(StorageType typeCode, Type dataType) {
- bool result;
- switch (typeCode) {
- case StorageType.Boolean:
- case StorageType.Char:
- case StorageType.SByte:
- case StorageType.Byte:
- case StorageType.Int16:
- case StorageType.UInt16:
- case StorageType.Int32:
- case StorageType.UInt32:
- case StorageType.Int64:
- case StorageType.UInt64:
- case StorageType.Single:
- case StorageType.Double:
- case StorageType.Decimal:
- case StorageType.DateTime:
- case StorageType.DateTimeOffset:
- case StorageType.BigInteger:
- case StorageType.TimeSpan:
- case StorageType.Guid:
- case StorageType.SqlBinary:
- case StorageType.SqlBoolean:
- case StorageType.SqlByte:
- case StorageType.SqlDateTime:
- case StorageType.SqlDecimal:
- case StorageType.SqlDouble:
- case StorageType.SqlGuid:
- case StorageType.SqlInt16:
- case StorageType.SqlInt32:
- case StorageType.SqlInt64:
- case StorageType.SqlMoney:
- case StorageType.SqlSingle:
- case StorageType.SqlString:
- result = true;
- break;
-
- case StorageType.String:
- case StorageType.ByteArray:
- case StorageType.CharArray:
- case StorageType.Type:
- case StorageType.Uri:
- case StorageType.SqlBytes:
- case StorageType.SqlChars:
- result = false;
- break;
-
- default:
- result = dataType.IsValueType;
- break;
- }
- Debug.Assert(result == dataType.IsValueType, "typeCode mismatches dataType");
- return result;
- }
-
- internal static void ImplementsInterfaces(
- StorageType typeCode,
- Type dataType,
- out bool sqlType,
- out bool nullable,
- out bool xmlSerializable,
- out bool changeTracking,
- out bool revertibleChangeTracking)
- {
- Debug.Assert(typeCode == GetStorageType(dataType), "typeCode mismatches dataType");
- if (IsSqlType(typeCode)) {
- sqlType = true;
- nullable = true;
- changeTracking = false;
- revertibleChangeTracking = false;
- xmlSerializable = true;
- }
- else if (StorageType.Empty != typeCode) {
- sqlType = false;
- nullable = false;
- changeTracking = false;
- revertibleChangeTracking = false;
- xmlSerializable = false;
- }
- else {
- // Non-standard type - look it up in the dictionary or add it if not found
- Tuple interfaces = _typeImplementsInterface.GetOrAdd(dataType, _inspectTypeForInterfaces);
- sqlType = false;
- nullable = interfaces.Item1;
- changeTracking = interfaces.Item2;
- revertibleChangeTracking = interfaces.Item3;
- xmlSerializable = interfaces.Item4;
- }
- Debug.Assert(nullable == typeof(System.Data.SqlTypes.INullable).IsAssignableFrom(dataType), "INullable");
- Debug.Assert(changeTracking == typeof(System.ComponentModel.IChangeTracking).IsAssignableFrom(dataType), "IChangeTracking");
- Debug.Assert(revertibleChangeTracking == typeof(System.ComponentModel.IRevertibleChangeTracking).IsAssignableFrom(dataType), "IRevertibleChangeTracking");
- Debug.Assert(xmlSerializable == typeof(System.Xml.Serialization.IXmlSerializable).IsAssignableFrom(dataType), "IXmlSerializable");
- }
-
- private static Tuple InspectTypeForInterfaces(Type dataType) {
- Debug.Assert(dataType != null, "Type should not be null");
-
- return new Tuple(
- typeof(System.Data.SqlTypes.INullable).IsAssignableFrom(dataType),
- typeof(System.ComponentModel.IChangeTracking).IsAssignableFrom(dataType),
- typeof(System.ComponentModel.IRevertibleChangeTracking).IsAssignableFrom(dataType),
- typeof(System.Xml.Serialization.IXmlSerializable).IsAssignableFrom(dataType));
- }
-
- internal static bool ImplementsINullableValue(StorageType typeCode, Type dataType) {
- Debug.Assert(typeCode == GetStorageType(dataType), "typeCode mismatches dataType");
- return ((StorageType.Empty == typeCode) && dataType.IsGenericType && (dataType.GetGenericTypeDefinition() == typeof(System.Nullable<>)));
- }
-
- public static bool IsObjectNull(object value) {
- return ((null == value) || (DBNull.Value == value) || IsObjectSqlNull(value));
- }
-
- public static bool IsObjectSqlNull(object value) {
- INullable inullable = (value as INullable);
- return ((null != inullable) && inullable.IsNull);
- }
-
- internal object GetEmptyStorageInternal(int recordCount) {
- return GetEmptyStorage(recordCount);
- }
-
- internal void CopyValueInternal(int record, object store, BitArray nullbits, int storeIndex) {
- CopyValue(record, store, nullbits, storeIndex);
- }
-
- internal void SetStorageInternal(object store, BitArray nullbits) {
- SetStorage(store, nullbits);
- }
-
- abstract protected Object GetEmptyStorage(int recordCount);
- abstract protected void CopyValue(int record, object store, BitArray nullbits, int storeIndex);
- abstract protected void SetStorage(object store, BitArray nullbits);
- protected void SetNullStorage(BitArray nullbits) {
- dbNullBits = nullbits;
- }
-
- /// wrapper around Type.GetType
- /// assembly qualified type name or one of the special known types
- /// Type or null if not found
- /// when type implements IDynamicMetaObjectProvider and not IXmlSerializable
- ///
- /// Types like "System.Guid" will load regardless of AssemblyQualifiedName because they are special
- /// Types like "System.Data.SqlTypes.SqlString" will load because they are in the same assembly as this code
- /// Types like "System.Numerics.BigInteger" won't load because they are not special and not same assembly as this code
- ///
- internal static Type GetType(string value) {
- Type dataType = Type.GetType(value); // throwOnError=false, ignoreCase=fase
- if (null == dataType) {
- if ("System.Numerics.BigInteger" == value) {
- dataType = typeof(System.Numerics.BigInteger);
- }
- }
-
- // Dev10 671061: prevent reading type from schema which implements IDynamicMetaObjectProvider and not IXmlSerializable
- // the check here prevents the type from being loaded in schema or as instance data (when DataType is object)
- ObjectStorage.VerifyIDynamicMetaObjectProvider(dataType);
- return dataType;
- }
-
- /// wrapper around Type.AssemblyQualifiedName
- ///
- /// qualified name when writing in xml
- /// when type implements IDynamicMetaObjectProvider and not IXmlSerializable
- internal static string GetQualifiedName(Type type)
- {
- Debug.Assert(null != type, "null type");
- ObjectStorage.VerifyIDynamicMetaObjectProvider(type);
- return type.AssemblyQualifiedName;
- }
- }
-}
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Common/src/Microsoft/Data/Common/DbConnectionPoolKey.cs b/src/Microsoft.Data.SqlClient/netfx/src/Common/src/Microsoft/Data/Common/DbConnectionPoolKey.cs
deleted file mode 100644
index 0334016847..0000000000
--- a/src/Microsoft.Data.SqlClient/netfx/src/Common/src/Microsoft/Data/Common/DbConnectionPoolKey.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace Microsoft.Data.Common
-{
-
- using System;
-
- // DbConnectionPoolKey: Base class implementation of a key to connection pool groups
- // Only connection string is used as a key
- internal class DbConnectionPoolKey : ICloneable
- {
- private string _connectionString;
-
- internal DbConnectionPoolKey(string connectionString)
- {
- _connectionString = connectionString;
- }
-
- protected DbConnectionPoolKey(DbConnectionPoolKey key)
- {
- _connectionString = key.ConnectionString;
- }
-
- object ICloneable.Clone()
- {
- return new DbConnectionPoolKey(this);
- }
-
- internal virtual string ConnectionString
- {
- get
- {
- return _connectionString;
- }
-
- set
- {
- _connectionString = value;
- }
- }
-
- public override bool Equals(object obj)
- {
- if (obj == null)
- {
- return false;
- }
-
- return (obj is DbConnectionPoolKey key && _connectionString == key._connectionString);
- }
-
- public override int GetHashCode()
- {
- return _connectionString == null ? 0 : _connectionString.GetHashCode();
- }
- }
-}
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Common/src/Microsoft/Data/Common/MultipartIdentifier.cs b/src/Microsoft.Data.SqlClient/netfx/src/Common/src/Microsoft/Data/Common/MultipartIdentifier.cs
deleted file mode 100644
index a7c106baed..0000000000
--- a/src/Microsoft.Data.SqlClient/netfx/src/Common/src/Microsoft/Data/Common/MultipartIdentifier.cs
+++ /dev/null
@@ -1,293 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace Microsoft.Data.Common
-{
- using System;
- using System.Text;
-
- internal class MultipartIdentifier
- {
- private const int MaxParts = 4;
- internal const int ServerIndex = 0;
- internal const int CatalogIndex = 1;
- internal const int SchemaIndex = 2;
- internal const int TableIndex = 3;
-
- /*
- Left quote strings need to correspond 1 to 1 with the right quote strings
- example: "ab" "cd", passed in for the left and the right quote
- would set a or b as a starting quote character.
- If a is the starting quote char then c would be the ending quote char
- otherwise if b is the starting quote char then d would be the ending quote character.
- */
- internal static string[] ParseMultipartIdentifier(string name, string leftQuote, string rightQuote, string property, bool ThrowOnEmptyMultipartName)
- {
- return ParseMultipartIdentifier(name, leftQuote, rightQuote, '.', MaxParts, true, property, ThrowOnEmptyMultipartName);
- }
-
- private enum MPIState
- {
- MPI_Value,
- MPI_ParseNonQuote,
- MPI_LookForSeparator,
- MPI_LookForNextCharOrSeparator,
- MPI_ParseQuote,
- MPI_RightQuote,
- }
-
- /* Core function for parsing the multipart identifier string.
- * parameters: name - string to parse
- * leftquote: set of characters which are valid quoteing characters to initiate a quote
- * rightquote: set of characters which are valid to stop a quote, array index's correspond to the the leftquote array.
- * separator: separator to use
- * limit: number of names to parse out
- * removequote:to remove the quotes on the returned string
- */
- private static void IncrementStringCount(string name, string[] ary, ref int position, string property)
- {
- ++position;
- int limit = ary.Length;
- if (position >= limit)
- {
- throw ADP.InvalidMultipartNameToManyParts(property, name, limit);
- }
- ary[position] = string.Empty;
- }
-
- private static bool IsWhitespace(char ch)
- {
- return Char.IsWhiteSpace(ch);
- }
-
- internal static string[] ParseMultipartIdentifier(string name, string leftQuote, string rightQuote, char separator, int limit, bool removequotes, string property, bool ThrowOnEmptyMultipartName)
- {
-
- if (limit <= 0)
- {
- throw ADP.InvalidMultipartNameToManyParts(property, name, limit);
- }
-
- if (-1 != leftQuote.IndexOf(separator) || -1 != rightQuote.IndexOf(separator) || leftQuote.Length != rightQuote.Length)
- {
- throw ADP.InvalidMultipartNameIncorrectUsageOfQuotes(property, name);
- }
-
- string[] parsedNames = new string[limit]; // return string array
- int stringCount = 0; // index of current string in the buffer
- MPIState state = MPIState.MPI_Value; // Initialize the starting state
-
- StringBuilder sb = new StringBuilder(name.Length); // String buffer to hold the string being currently built, init the string builder so it will never be resized
- StringBuilder whitespaceSB = null; // String buffer to hold white space used when parsing nonquoted strings 'a b . c d' = 'a b' and 'c d'
- char rightQuoteChar = ' '; // Right quote character to use given the left quote character found.
- for (int index = 0; index < name.Length; ++index)
- {
- char testchar = name[index];
- switch (state)
- {
- case MPIState.MPI_Value:
- {
- int quoteIndex;
- if (IsWhitespace(testchar))
- { // Is White Space then skip the whitespace
- continue;
- }
- else
- if (testchar == separator)
- { // If we found a separator, no string was found, initialize the string we are parsing to Empty and the next one to Empty.
- // This is NOT a redundant setting of string.Empty it solves the case where we are parsing ".foo" and we should be returning null, null, empty, foo
- parsedNames[stringCount] = string.Empty;
- IncrementStringCount(name, parsedNames, ref stringCount, property);
- }
- else
- if (-1 != (quoteIndex = leftQuote.IndexOf(testchar)))
- { // If we are a left quote
- rightQuoteChar = rightQuote[quoteIndex]; // record the corresponding right quote for the left quote
- sb.Length = 0;
- if (!removequotes)
- {
- sb.Append(testchar);
- }
- state = MPIState.MPI_ParseQuote;
- }
- else
- if (-1 != rightQuote.IndexOf(testchar))
- { // If we shouldn't see a right quote
- throw ADP.InvalidMultipartNameIncorrectUsageOfQuotes(property, name);
- }
- else
- {
- sb.Length = 0;
- sb.Append(testchar);
- state = MPIState.MPI_ParseNonQuote;
- }
- break;
- }
-
- case MPIState.MPI_ParseNonQuote:
- {
- if (testchar == separator)
- {
- parsedNames[stringCount] = sb.ToString(); // set the currently parsed string
- IncrementStringCount(name, parsedNames, ref stringCount, property);
- state = MPIState.MPI_Value;
- }
- else // Quotes are not valid inside a non-quoted name
- if (-1 != rightQuote.IndexOf(testchar))
- {
- throw ADP.InvalidMultipartNameIncorrectUsageOfQuotes(property, name);
- }
- else
- if (-1 != leftQuote.IndexOf(testchar))
- {
- throw ADP.InvalidMultipartNameIncorrectUsageOfQuotes(property, name);
- }
- else
- if (IsWhitespace(testchar))
- { // If it is Whitespace
- parsedNames[stringCount] = sb.ToString(); // Set the currently parsed string
- if (null == whitespaceSB)
- {
- whitespaceSB = new StringBuilder();
- }
- whitespaceSB.Length = 0;
- whitespaceSB.Append(testchar); // start to record the white space, if we are parsing a name like "foo bar" we should return "foo bar"
- state = MPIState.MPI_LookForNextCharOrSeparator;
- }
- else
- {
- sb.Append(testchar);
- }
- break;
- }
-
- case MPIState.MPI_LookForNextCharOrSeparator:
- {
- if (!IsWhitespace(testchar))
- { // If it is not whitespace
- if (testchar == separator)
- {
- IncrementStringCount(name, parsedNames, ref stringCount, property);
- state = MPIState.MPI_Value;
- }
- else
- { // If its not a separator and not whitespace
- sb.Append(whitespaceSB);
- sb.Append(testchar);
- parsedNames[stringCount] = sb.ToString(); // Need to set the name here in case the string ends here.
- state = MPIState.MPI_ParseNonQuote;
- }
- }
- else
- {
- whitespaceSB.Append(testchar);
- }
- break;
- }
-
- case MPIState.MPI_ParseQuote:
- {
- if (testchar == rightQuoteChar)
- { // if se are on a right quote see if we are escaping the right quote or ending the quoted string
- if (!removequotes)
- {
- sb.Append(testchar);
- }
- state = MPIState.MPI_RightQuote;
- }
- else
- {
- sb.Append(testchar); // Append what we are currently parsing
- }
- break;
- }
-
- case MPIState.MPI_RightQuote:
- {
- if (testchar == rightQuoteChar)
- { // If the next char is a another right quote then we were escaping the right quote
- sb.Append(testchar);
- state = MPIState.MPI_ParseQuote;
- }
- else
- if (testchar == separator)
- { // If its a separator then record what we've parsed
- parsedNames[stringCount] = sb.ToString();
- IncrementStringCount(name, parsedNames, ref stringCount, property);
- state = MPIState.MPI_Value;
- }
- else
- if (!IsWhitespace(testchar))
- { // If it is not white space we got problems
- throw ADP.InvalidMultipartNameIncorrectUsageOfQuotes(property, name);
- }
- else
- { // It is a whitespace character so the following char should be whitespace, separator, or end of string anything else is bad
- parsedNames[stringCount] = sb.ToString();
- state = MPIState.MPI_LookForSeparator;
- }
- break;
- }
-
- case MPIState.MPI_LookForSeparator:
- {
- if (!IsWhitespace(testchar))
- { // If it is not whitespace
- if (testchar == separator)
- { // If it is a separator
- IncrementStringCount(name, parsedNames, ref stringCount, property);
- state = MPIState.MPI_Value;
- }
- else
- { // Otherwise not a separator
- throw ADP.InvalidMultipartNameIncorrectUsageOfQuotes(property, name);
- }
- }
- break;
- }
- }
- }
-
- // Resolve final states after parsing the string
- switch (state)
- {
- case MPIState.MPI_Value: // These states require no extra action
- case MPIState.MPI_LookForSeparator:
- case MPIState.MPI_LookForNextCharOrSeparator:
- break;
-
- case MPIState.MPI_ParseNonQuote: // Dump what ever was parsed
- case MPIState.MPI_RightQuote:
- parsedNames[stringCount] = sb.ToString();
- break;
-
- case MPIState.MPI_ParseQuote: // Invalid Ending States
- default:
- throw ADP.InvalidMultipartNameIncorrectUsageOfQuotes(property, name);
- }
-
- if (parsedNames[0] == null)
- {
- if (ThrowOnEmptyMultipartName)
- {
- throw ADP.InvalidMultipartName(property, name); // Name is entirely made up of whitespace
- }
- }
- else
- {
- // Shuffle the parsed name, from left justification to right justification, ie [a][b][null][null] goes to [null][null][a][b]
- int offset = limit - stringCount - 1;
- if (offset > 0)
- {
- for (int x = limit - 1; x >= offset; --x)
- {
- parsedNames[x] = parsedNames[x - offset];
- parsedNames[x - offset] = null;
- }
- }
- }
- return parsedNames;
- }
- }
-}
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
index 8096839c85..7998f01935 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
@@ -103,6 +103,12 @@
Microsoft\Data\Common\ActivityCorrelator.cs
+
+ Microsoft\Data\Common\DbConnectionPoolKey.cs
+
+
+ Microsoft\Data\Common\MultipartIdentifier.cs
+
Microsoft\Data\Sql\SqlNotificationRequest.cs
@@ -417,8 +423,6 @@
-
-
@@ -535,4 +539,4 @@
-
\ No newline at end of file
+
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Microsoft/Data/Common/DbConnectionPoolKey.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/DbConnectionPoolKey.cs
similarity index 100%
rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/Microsoft/Data/Common/DbConnectionPoolKey.cs
rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/DbConnectionPoolKey.cs
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Microsoft/Data/Common/MultipartIdentifier.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/MultipartIdentifier.cs
similarity index 100%
rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/Microsoft/Data/Common/MultipartIdentifier.cs
rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/MultipartIdentifier.cs
diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj
index ed83505b6a..c41a99cc4d 100644
--- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj
+++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj
@@ -26,6 +26,7 @@
+
@@ -55,6 +56,7 @@
+
diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/MultipartIdentifierTests.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/MultipartIdentifierTests.cs
new file mode 100644
index 0000000000..6e6ba3a751
--- /dev/null
+++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/MultipartIdentifierTests.cs
@@ -0,0 +1,260 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Microsoft.Data.Common;
+using Xunit;
+
+namespace Microsoft.Data.SqlClient.Tests
+{
+ public class MultipartIdentifierTests
+ {
+ [Fact]
+ public void SingleUnquoted() => RunParse("foo", new[] { "foo" });
+
+ [Fact]
+ public void SingleUnquotedOvercount() => RunParse("foo", new[] { null, "foo" }, maxCount: 2);
+
+ [Fact]
+ public void SingleUnquotedContainsWhitespace() => RunParse("foo bar", new[] { "foo bar" });
+
+ [Fact]
+ public void SingleUnquotedStartWithShitespace() => RunParse(" foo", new[] { "foo" });
+
+ [Fact]
+ public void SingleUnquotedEndWithShitespace() => RunParse("foo ", new[] { "foo" });
+
+ [Fact]
+ public void SingleQuotedRemoveQuote() => RunParse("[foo]", new[] { "[foo]" }, false);
+
+ [Fact]
+ public void SingleQuotedKeepQuote() => RunParse("[foo]", new[] { "foo" }, true);
+
+ [Fact]
+ public void SingleQuotedLeadingWhitespace() => RunParse("[ foo]", new[] { " foo" }, true);
+
+ [Fact]
+ public void SingleQuotedTrailingWhitespace() => RunParse("[foo ]", new[] { "foo " }, true);
+
+ [Fact]
+ public void QuotedContainsWhitespace() => RunParse("[foo bar]", new[] { "foo bar" }, true);
+
+ [Fact]
+ public void SingleQuotedContainsAndTrailingWhitespace() => RunParse("[foo bar ]", new[] { "foo bar " });
+
+ [Fact]
+ public void SingleQuotedInternalAndLeadingWhitespace() => RunParse("[ foo bar]", new[] { " foo bar" });
+
+ [Fact]
+ public void SingleQuotedContainsAndLeadingAndTrailingWhitespace() => RunParse("[ foo bar ]", new[] { " foo bar " });
+
+ [Fact]
+ public void SingleQuotedEscapedQuote() => RunParse("[foo]]bar]", new[] { "foo]bar" }, true);
+
+
+ [Fact]
+ public void DoubleUnquotedParts() => RunParse("foo.bar", new[] { "foo", "bar" });
+
+ [Fact]
+ public void DoubleUnquotedPartContainsTrailngWhitespace() => RunParse("foo .bar", new[] { "foo", "bar" });
+
+ [Fact]
+ public void DoubleUnquotedPartContainsLeadingWhitespace() => RunParse("foo. bar", new[] { "foo", "bar" });
+
+ [Fact]
+ public void DoubleUnquotedEmptyFirst() => RunParse(".bar", new[] { "", "bar" });
+
+ [Fact]
+ public void DoubleUnquotedEmptyLast() => RunParse("foo.", new[] { "foo", "" });
+
+ [Fact]
+ public void DoubleQuotedParts() => RunParse("[foo].[bar]", new string[] { "foo", "bar" });
+
+ [Fact]
+ public void DoubleQuotedPartContainsLeadingWhitespace() => RunParse("[foo]. [bar]", new[] { "foo", "bar" });
+
+ [Fact]
+ public void DoubleQuotedPartContainsTrailngWhitespace() => RunParse("[foo] .[bar]", new[] { "foo", "bar" });
+
+
+ [Fact]
+ public void TripleUnquotedParts() => RunParse("foo.bar.ed", new[] { "foo", "bar", "ed" });
+
+ [Fact]
+ public void TripleUnquotedMissingMiddle() => RunParse("foo..bar", new[] { "foo", "", "bar" });
+
+ [Fact]
+ public void TripleUnquotedPartContainsTrailingWhitespace() => RunParse("foo .bar .ed", new[] { "foo", "bar", "ed" });
+
+ [Fact]
+ public void TripleUnquotedPartContainsEmptyAndTrailngWhitespace() => RunParse(" .bar .ed", new[] { "", "bar", "ed" });
+
+ [Fact]
+ public void TripleUnquotedPartContainsLeadingWhitespace() => RunParse("foo. bar.", new[] { "foo", "bar", "" });
+
+ [Fact]
+ public void TripleUnquotedEmptyPart() => RunParse(".bar", new[] { "", "bar" });
+
+ [Fact]
+ public void TripleQuotedParts() => RunParse("[foo].[bar]", new[] { "foo", "bar" });
+
+ [Fact]
+ public void TripleQuotedPartContainsLeadingWhitespace() => RunParse("[foo]. [bar]", new[] { "foo", "bar" });
+
+ [Fact]
+ public void TripleQuotedPartContainsTrailngWhitespace() => RunParse("[foo] .[bar]", new[] { "foo", "bar" });
+
+ [Fact]
+ public void InvalidUnquotedEmpty() => ThrowParse("", new[] { "" });
+
+ [Fact]
+ public void InvalidContainsOpen() => ThrowParse("foo[bar", new[] { "foo[bar" });
+
+ [Fact]
+ public void InvalidContainsClose() => ThrowParse("foo]bar", new[] { "foo]bar" });
+
+ [Fact]
+ public void InvalidStartsWithClose() => ThrowParse("]bar", new[] { "]bar" });
+
+ [Fact]
+ public void InvalidEndsWithClose() => ThrowParse("bar]", new[] { "bar]" });
+
+ [Fact]
+ public void InvalidUnfinishedBraceOpen() => ThrowParse("[foo", new[] { "[foo" });
+
+ [Fact]
+ public void InvalidUnfinishedQuoteOpen() => ThrowParse("\"foo", new[] { "\"foo" });
+
+ [Fact]
+ public void InvalidCapacity()
+ {
+ ThrowParse("", Array.Empty());
+ }
+
+ [Fact]
+ public void InvalidLeftQuote()
+ {
+ ThrowParse("foo", new[] { "foo" }, leftQuotes: "[.");
+ }
+
+ [Fact]
+ public void InvalidRightQuote()
+ {
+ ThrowParse("foo", new[] { "foo" }, rightQuotes: "[.");
+ }
+
+ [Fact]
+ public void InvalidQuotedPartContainsTrailngNonWhitespace() => ThrowParse("[foo]!.[bar]", new[] { "foo", "bar" });
+
+ [Fact]
+ public void InvalidQuotedPartContainsTrailngWhiteSpaceThenNonWhitespace() => ThrowParse("[foo] !.[bar]", new[] { "foo", "bar" });
+
+ [Fact]
+ public void InvalidTooManyParts_2to1() => ThrowParse("foo.bar", new[] { "foo" });
+
+ [Fact]
+ public void InvalidTooManyPartsEndsInSeparator() => ThrowParse("a.", 1);
+
+ [Fact]
+ public void InvalidTooManyPartsAfterTrailingWhitespace() => ThrowParse("foo .bar .ed", 1);
+
+ [Fact]
+ public void InvalidTooManyPartsEndsWithCloseQuote() => ThrowParse("a.[b]", 1);
+
+ [Fact]
+ public void InvalidTooManyPartsEndsWithWhitespace() => ThrowParse("a.foo ", 1);
+
+ [Fact]
+ public void InvalidTooManyPartsQuotedPartContainsLeadingWhitespace() => ThrowParse("a.[b].c", 1);
+
+ [Fact]
+ public void InvalidTooManyPartsWhiteSpaceBeforeSeparator() => ThrowParse("a.b ..", 2);
+
+ [Fact]
+ public void InvalidTooManyPartsAfterCloseQuote() => ThrowParse("a.[b] .c", 1);
+
+ [Fact]
+ public void InvalidTooManyPartsSeparatorAfterPart() => ThrowParse("a.b.c", 1);
+
+
+ private static void RunParse(string name, string[] expected, bool removeQuotes = true, int maxCount = 0)
+ {
+ if (maxCount == 0)
+ {
+ for (int index = 0; index < expected.Length; index++)
+ {
+ if (expected[index] != null)
+ {
+ maxCount += 1;
+ }
+ }
+ }
+
+ string[] originalParts = MultipartIdentifier.ParseMultipartIdentifier(name, "[\"", "]\"", '.', maxCount, removeQuotes, "", true);
+
+ for (int index = 0; index < expected.Length; index++)
+ {
+ string expectedPart = expected[index];
+ string originalPart = originalParts[index];
+
+ Assert.Equal(expectedPart, originalPart);
+ }
+ }
+
+ private static void ThrowParse(string name, string[] expected, bool removeQuotes = true, string leftQuotes = "[\"", string rightQuotes = "]\"", char separator = '.')
+ where TException : Exception
+ {
+ int maxCount = 0;
+ for (int index = 0; index < expected.Length; index++)
+ {
+ if (expected[index] != null)
+ {
+ maxCount += 1;
+ }
+ }
+
+ Exception originalException = Assert.Throws(() =>
+ MultipartIdentifier.ParseMultipartIdentifier(name, leftQuotes, rightQuotes, separator, maxCount, removeQuotes, "", true)
+ );
+
+ Assert.NotNull(originalException);
+ }
+
+
+
+ private static void ThrowParse(string name, int expectedLength, bool removeQuotes = true, string leftQuotes = "[\"", string rightQuotes = "]\"", char separator = '.')
+ {
+ Exception originalException = Assert.Throws(
+ () =>
+ {
+ MultipartIdentifier.ParseMultipartIdentifier(name, leftQuotes, rightQuotes, separator, expectedLength, removeQuotes, "test", true);
+ }
+ );
+ Assert.NotNull(originalException);
+ }
+
+ }
+}
+
+namespace Microsoft.Data.Common
+{
+ // this is needed for the inclusion of MultipartIdentifier class
+ internal class ADP
+ {
+ internal static ArgumentException InvalidMultipartName(string property, string name)
+ {
+ return new ArgumentException();
+ }
+
+ internal static ArgumentException InvalidMultipartNameIncorrectUsageOfQuotes(string property, string name)
+ {
+ return new ArgumentException();
+ }
+
+ internal static ArgumentException InvalidMultipartNameToManyParts(string property, string name, int limit)
+ {
+ return new ArgumentException();
+ }
+ }
+}
From d02bf4badb659f64886391628404901ba1b3b236 Mon Sep 17 00:00:00 2001
From: Wraith
Date: Tue, 22 Dec 2020 19:24:29 +0000
Subject: [PATCH 014/509] Update similar files, Share more files (#835)
---
.../src/Microsoft.Data.SqlClient.csproj | 12 +-
.../Data/SqlClient/Server/SqlNorm.cs | 43 +-
.../Microsoft/Data/SqlClient/Server/SqlSer.cs | 28 +-
.../Data/SqlClient/Server/ValueUtilsSmi.cs | 1 -
.../netfx/src/Microsoft.Data.SqlClient.csproj | 12 +-
.../Data/SqlClient/Server/SqlMetaData.cs | 1925 -----------------
.../Data/SqlClient/Server/SqlRecordBuffer.cs | 615 ------
.../SqlUserDefinedAggregateAttribute.cs | 140 --
.../Data/SqlClient/Server/ValueUtilsSmi.cs | 213 +-
.../Microsoft/Data/SqlClient/Server/sqlser.cs | 135 +-
.../Data/SqlClient/Server/SqlMetaData.cs | 1438 +++++++-----
.../Data/SqlClient/Server/SqlRecordBuffer.cs | 0
.../SqlUserDefinedAggregateAttribute.cs | 20 +-
13 files changed, 1061 insertions(+), 3521 deletions(-)
delete mode 100644 src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/SqlMetaData.cs
delete mode 100644 src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/SqlRecordBuffer.cs
delete mode 100644 src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/SqlUserDefinedAggregateAttribute.cs
rename src/Microsoft.Data.SqlClient/{netcore => }/src/Microsoft/Data/SqlClient/Server/SqlMetaData.cs (57%)
rename src/Microsoft.Data.SqlClient/{netcore => }/src/Microsoft/Data/SqlClient/Server/SqlRecordBuffer.cs (100%)
rename src/Microsoft.Data.SqlClient/{netcore => }/src/Microsoft/Data/SqlClient/Server/SqlUserDefinedAggregateAttribute.cs (61%)
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
index 5a299ba2e1..3e7db7d945 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
@@ -123,12 +123,18 @@
Microsoft\Data\SqlClient\Server\SqlFunctionAttribute.cs
+
+ Microsoft\Data\SqlClient\Server\SqlMetaData.cs
+
Microsoft\Data\SqlClient\Server\SqlMethodAttribute.cs
Microsoft\Data\SqlClient\Server\SqlUserDefinedTypeAttribute.cs
+
+ Microsoft\Data\SqlClient\Server\SqlUserDefinedAggregateAttribute.cs
+
Microsoft\Data\SqlClient\ColumnEncryptionKeyInfo.cs
@@ -243,6 +249,9 @@
Microsoft\Data\SqlClient\Server\InvalidUdtException.cs
+
+ Microsoft\Data\SqlClient\Server\SqlRecordBuffer.cs
+
Microsoft\Data\SqlClient\SignatureVerificationCache.cs
@@ -313,7 +322,6 @@
-
@@ -364,10 +372,8 @@
-
-
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/SqlNorm.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/SqlNorm.cs
index 9ab047679c..e0c24c87fb 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/SqlNorm.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/SqlNorm.cs
@@ -16,32 +16,34 @@ namespace Microsoft.Data.SqlClient.Server
// a particular field.
internal sealed class FieldInfoEx : IComparable
{
- internal readonly int Offset;
- internal readonly FieldInfo FieldInfo;
- internal readonly Normalizer Normalizer;
+ private readonly int _offset;
internal FieldInfoEx(FieldInfo fi, int offset, Normalizer normalizer)
{
- FieldInfo = fi;
- Offset = offset;
Debug.Assert(normalizer != null, "normalizer argument should not be null!");
Normalizer = normalizer;
+ FieldInfo = fi;
+ _offset = offset;
}
+ internal FieldInfo FieldInfo { get; private set; }
+ internal Normalizer Normalizer { get; private set; }
// Sort fields by field offsets.
public int CompareTo(object other)
{
FieldInfoEx otherF = other as FieldInfoEx;
if (otherF == null)
+ {
return -1;
- return Offset.CompareTo(otherF.Offset);
+ }
+ return _offset.CompareTo(otherF._offset);
}
}
// The most complex normalizer, a udt normalizer
internal sealed class BinaryOrderedUdtNormalizer : Normalizer
{
- internal readonly FieldInfoEx[] FieldsToNormalize;
+ private readonly FieldInfoEx[] _fieldsToNormalize;
private int _size;
private byte[] _padBuffer;
internal readonly object NullInstance;
@@ -69,18 +71,18 @@ internal BinaryOrderedUdtNormalizer(Type t, bool isTopLevelUdt)
// get all the fields
FieldInfo[] fields = GetFields(t);
- FieldsToNormalize = new FieldInfoEx[fields.Length];
+ _fieldsToNormalize = new FieldInfoEx[fields.Length];
int i = 0;
foreach (FieldInfo fi in fields)
{
int offset = Marshal.OffsetOf(fi.DeclaringType, fi.Name).ToInt32();
- FieldsToNormalize[i++] = new FieldInfoEx(fi, offset, GetNormalizer(fi.FieldType));
+ _fieldsToNormalize[i++] = new FieldInfoEx(fi, offset, GetNormalizer(fi.FieldType));
}
//sort by offset
- Array.Sort(FieldsToNormalize);
+ Array.Sort(_fieldsToNormalize);
//if this is not a top-level udt, do setup for null values.
//null values need to compare less than all other values,
//so prefix a null byte indicator.
@@ -138,8 +140,10 @@ private object DeNormalizeInternal(Type t, Stream s)
}
}
if (result == null)
+ {
result = Activator.CreateInstance(t);
- foreach (FieldInfoEx myField in FieldsToNormalize)
+ }
+ foreach (FieldInfoEx myField in _fieldsToNormalize)
{
myField.Normalizer.DeNormalize(myField.FieldInfo, result, s);
}
@@ -173,7 +177,7 @@ internal override void Normalize(FieldInfo fi, object obj, Stream s)
}
}
- foreach (FieldInfoEx myField in FieldsToNormalize)
+ foreach (FieldInfoEx myField in _fieldsToNormalize)
{
myField.Normalizer.Normalize(myField.FieldInfo, inner, s);
}
@@ -189,10 +193,14 @@ internal override int Size
get
{
if (_size != 0)
+ {
return _size;
+ }
if (IsNullable && !_isTopLevelUdt)
+ {
_size = 1;
- foreach (FieldInfoEx myField in FieldsToNormalize)
+ }
+ foreach (FieldInfoEx myField in _fieldsToNormalize)
{
_size += myField.Normalizer.Size;
}
@@ -238,7 +246,9 @@ internal static Normalizer GetNormalizer(Type t)
n = new BinaryOrderedUdtNormalizer(t, false);
}
if (n == null)
+ {
throw new Exception(StringsHelper.GetString(Strings.SQL_CannotCreateNormalizer, t.FullName));
+ }
n._skipNormalize = false;
return n;
}
@@ -250,15 +260,14 @@ internal static Normalizer GetNormalizer(Type t)
protected void FlipAllBits(byte[] b)
{
for (int i = 0; i < b.Length; i++)
+ {
b[i] = (byte)~b[i];
+ }
}
protected object GetValue(FieldInfo fi, object obj) => fi.GetValue(obj);
- protected void SetValue(FieldInfo fi, object recvr, object value)
- {
- fi.SetValue(recvr, value);
- }
+ protected void SetValue(FieldInfo fi, object recvr, object value) => fi.SetValue(recvr, value);
internal abstract int Size { get; }
}
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/SqlSer.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/SqlSer.cs
index a0bbc2a463..c9f1536f50 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/SqlSer.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/SqlSer.cs
@@ -173,14 +173,12 @@ private static Serializer GetNewSerializer(Type t)
// The base serializer class.
internal abstract class Serializer
{
+ protected Type _type;
+
public abstract object Deserialize(Stream s);
public abstract void Serialize(Stream s, object o);
- protected Type _type;
- protected Serializer(Type t)
- {
- _type = t;
- }
+ protected Serializer(Type t) => _type = t;
}
internal sealed class NormalizedSerializer : Serializer
@@ -197,10 +195,7 @@ internal NormalizedSerializer(Type t) : base(t)
_maxSize = _normalizer.Size;
}
- public override void Serialize(Stream s, object o)
- {
- _normalizer.NormalizeTopObject(o, s);
- }
+ public override void Serialize(Stream s, object o) => _normalizer.NormalizeTopObject(o, s);
public override object Deserialize(Stream s) => _normalizer.DeNormalizeTopObject(_type, s);
}
@@ -253,22 +248,13 @@ private void DontDoIt()
public override long Position
{
- get
- {
- return _size;
- }
- set
- {
- _size = value;
- }
+ get => _size;
+ set => _size = value;
}
public override long Length => _size;
- public override void SetLength(long value)
- {
- _size = value;
- }
+ public override void SetLength(long value) => _size = value;
public override long Seek(long value, SeekOrigin loc)
{
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/ValueUtilsSmi.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/ValueUtilsSmi.cs
index 43a71f0eb5..cdf0802ef3 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/ValueUtilsSmi.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/ValueUtilsSmi.cs
@@ -2729,7 +2729,6 @@ private static void SetUdt_LengthChecked(SmiEventSink_Default sink, ITypedSetter
}
}
-
//
// Semantics support routines
//
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
index 7998f01935..cf8c458f2e 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
@@ -178,12 +178,21 @@
Microsoft\Data\SqlClient\Server\SqlFunctionAttribute.cs
+
+ Microsoft\Data\SqlClient\Server\SqlMetaData.cs
+
Microsoft\Data\SqlClient\Server\SqlMethodAttribute.cs
Microsoft\Data\SqlClient\Server\SqlUserDefinedTypeAttribute.cs
+
+ Microsoft\Data\SqlClient\Server\SqlUserDefinedAggregateAttribute.cs
+
+
+ Microsoft\Data\SqlClient\Server\SqlRecordBuffer.cs
+
Microsoft\Data\SqlClient\ColumnEncryptionKeyInfo.cs
@@ -337,8 +346,6 @@
-
-
@@ -465,7 +472,6 @@
-
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/SqlMetaData.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/SqlMetaData.cs
deleted file mode 100644
index a3dd3edc4f..0000000000
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/SqlMetaData.cs
+++ /dev/null
@@ -1,1925 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using System.Data;
-using System.Data.SqlTypes;
-using System.Globalization;
-using Microsoft.Data.Common;
-
-namespace Microsoft.Data.SqlClient.Server
-{
- ///
- // class SqlMetaData
- // Simple immutable implementation of the a metadata-holding class. Only
- // complexities are:
- // 1) enforcing immutability.
- // 2) Inferring type from a value.
- // 3) Adjusting a value to match the metadata.
- public sealed class SqlMetaData
- {
- private string m_strName;
- private long m_lMaxLength;
- private SqlDbType m_sqlDbType;
- private byte m_bPrecision;
- private byte m_bScale;
- private long m_lLocale;
- private SqlCompareOptions m_eCompareOptions;
- private string m_XmlSchemaCollectionDatabase;
- private string m_XmlSchemaCollectionOwningSchema;
- private string m_XmlSchemaCollectionName;
- private string m_serverTypeName;
- private bool m_bPartialLength;
- private Type m_udttype;
- private bool m_useServerDefault;
- private bool m_isUniqueKey;
- private SortOrder m_columnSortOrder;
- private int m_sortOrdinal;
-
- // unlimited (except by implementation) max-length.
- private const long x_lMax = -1;
- private const long x_lServerMaxUnicode = 4000;
- private const long x_lServerMaxANSI = 8000;
- private const long x_lServerMaxBinary = 8000;
- private const bool x_defaultUseServerDefault = false;
- private const bool x_defaultIsUniqueKey = false;
- private const SortOrder x_defaultColumnSortOrder = SortOrder.Unspecified;
- private const int x_defaultSortOrdinal = -1;
-
- private const SqlCompareOptions x_eDefaultStringCompareOptions = SqlCompareOptions.IgnoreCase
- | SqlCompareOptions.IgnoreKanaType | SqlCompareOptions.IgnoreWidth;
-
- ///
- // scalar types constructor without tvp extended properties
- public SqlMetaData(String name, SqlDbType dbType)
- {
- Construct(name, dbType, x_defaultUseServerDefault,
- x_defaultIsUniqueKey, x_defaultColumnSortOrder, x_defaultSortOrdinal);
- }
-
- ///
- // scalar types constructor
- public SqlMetaData(String name, SqlDbType dbType, bool useServerDefault,
- bool isUniqueKey, SortOrder columnSortOrder, int sortOrdinal)
- {
- Construct(name, dbType, useServerDefault,
- isUniqueKey, columnSortOrder, sortOrdinal);
- }
-
- ///
- // binary or string constructor with only max length
- // (for string types, locale and compare options will be picked up from the thread.
- public SqlMetaData(String name, SqlDbType dbType, long maxLength)
- {
- Construct(name, dbType, maxLength, x_defaultUseServerDefault,
- x_defaultIsUniqueKey, x_defaultColumnSortOrder, x_defaultSortOrdinal);
- }
-
- ///
- // binary or string constructor with only max length and tvp extended properties
- // (for string types, locale and compare options will be picked up from the thread.
- public SqlMetaData(String name, SqlDbType dbType, long maxLength, bool useServerDefault,
- bool isUniqueKey, SortOrder columnSortOrder, int sortOrdinal)
- {
- Construct(name, dbType, maxLength, useServerDefault,
- isUniqueKey, columnSortOrder, sortOrdinal);
- }
-
- ///
- // udt ctor without tvp extended properties
- public SqlMetaData(String name, SqlDbType dbType, Type userDefinedType)
- {
- Construct(name, dbType, userDefinedType, null, x_defaultUseServerDefault,
- x_defaultIsUniqueKey, x_defaultColumnSortOrder, x_defaultSortOrdinal);
- }
-
- ///
- // udt ctor without tvp extended properties
- public SqlMetaData(String name, SqlDbType dbType, Type userDefinedType, string serverTypeName)
- {
- Construct(name, dbType, userDefinedType, serverTypeName, x_defaultUseServerDefault,
- x_defaultIsUniqueKey, x_defaultColumnSortOrder, x_defaultSortOrdinal);
- }
-
- ///
- // udt ctor
- public SqlMetaData(String name, SqlDbType dbType, Type userDefinedType, string serverTypeName,
- bool useServerDefault, bool isUniqueKey, SortOrder columnSortOrder, int sortOrdinal)
- {
- Construct(name, dbType, userDefinedType, serverTypeName, useServerDefault,
- isUniqueKey, columnSortOrder, sortOrdinal);
- }
-
- ///
- // decimal ctor without tvp extended properties
- public SqlMetaData(String name, SqlDbType dbType, byte precision, byte scale)
- {
- Construct(name, dbType, precision, scale, x_defaultUseServerDefault,
- x_defaultIsUniqueKey, x_defaultColumnSortOrder, x_defaultSortOrdinal);
- }
-
- ///
- // decimal ctor
- public SqlMetaData(string name, SqlDbType dbType, byte precision, byte scale, bool useServerDefault,
- bool isUniqueKey, SortOrder columnSortOrder, int sortOrdinal)
- {
- Construct(name, dbType, precision, scale, useServerDefault,
- isUniqueKey, columnSortOrder, sortOrdinal);
- }
-
- ///
- // string type constructor with locale and compare options, no tvp extended properties
- public SqlMetaData(String name, SqlDbType dbType, long maxLength, long locale,
- SqlCompareOptions compareOptions)
- {
- Construct(name, dbType, maxLength, locale, compareOptions, x_defaultUseServerDefault,
- x_defaultIsUniqueKey, x_defaultColumnSortOrder, x_defaultSortOrdinal);
- }
-
- ///
- // string type constructor with locale and compare options
- public SqlMetaData(String name, SqlDbType dbType, long maxLength, long locale,
- SqlCompareOptions compareOptions, bool useServerDefault,
- bool isUniqueKey, SortOrder columnSortOrder, int sortOrdinal)
- {
- Construct(name, dbType, maxLength, locale, compareOptions, useServerDefault,
- isUniqueKey, columnSortOrder, sortOrdinal);
- }
-
- ///
- // typed xml ctor
- public SqlMetaData(String name, SqlDbType dbType, string database, string owningSchema,
- string objectName, bool useServerDefault, bool isUniqueKey,
- SortOrder columnSortOrder, int sortOrdinal)
- {
- Construct(name, dbType, database, owningSchema, objectName, useServerDefault,
- isUniqueKey, columnSortOrder, sortOrdinal);
- }
-
- ///
- // everything except xml schema and tvp properties ctor
- public SqlMetaData(String name, SqlDbType dbType, long maxLength, byte precision,
- byte scale, long locale, SqlCompareOptions compareOptions,
- Type userDefinedType) :
- this(name, dbType, maxLength, precision, scale, locale, compareOptions,
- userDefinedType, x_defaultUseServerDefault, x_defaultIsUniqueKey,
- x_defaultColumnSortOrder, x_defaultSortOrdinal)
- {
- }
-
- ///
- // everything except xml schema ctor
- public SqlMetaData(String name, SqlDbType dbType, long maxLength, byte precision,
- byte scale, long localeId, SqlCompareOptions compareOptions,
- Type userDefinedType, bool useServerDefault,
- bool isUniqueKey, SortOrder columnSortOrder, int sortOrdinal)
- {
- switch (dbType)
- {
- case SqlDbType.BigInt:
- case SqlDbType.Image:
- case SqlDbType.Timestamp:
- case SqlDbType.Bit:
- case SqlDbType.DateTime:
- case SqlDbType.SmallDateTime:
- case SqlDbType.Real:
- case SqlDbType.Int:
- case SqlDbType.Money:
- case SqlDbType.SmallMoney:
- case SqlDbType.Float:
- case SqlDbType.UniqueIdentifier:
- case SqlDbType.SmallInt:
- case SqlDbType.TinyInt:
- case SqlDbType.Xml:
- case SqlDbType.Date:
- Construct(name, dbType, useServerDefault, isUniqueKey, columnSortOrder, sortOrdinal);
- break;
- case SqlDbType.Binary:
- case SqlDbType.VarBinary:
- Construct(name, dbType, maxLength, useServerDefault, isUniqueKey, columnSortOrder, sortOrdinal);
- break;
- case SqlDbType.Char:
- case SqlDbType.NChar:
- case SqlDbType.NVarChar:
- case SqlDbType.VarChar:
- Construct(name, dbType, maxLength, localeId, compareOptions, useServerDefault, isUniqueKey, columnSortOrder, sortOrdinal);
- break;
- case SqlDbType.NText:
- case SqlDbType.Text:
- // SQLBU # : We should ignore user's max length and use Max instead to avoid exception
- Construct(name, dbType, Max, localeId, compareOptions, useServerDefault, isUniqueKey, columnSortOrder, sortOrdinal);
- break;
- case SqlDbType.Decimal:
- case SqlDbType.Time:
- case SqlDbType.DateTime2:
- case SqlDbType.DateTimeOffset:
- Construct(name, dbType, precision, scale, useServerDefault, isUniqueKey, columnSortOrder, sortOrdinal);
- break;
- case SqlDbType.Variant:
- Construct(name, dbType, useServerDefault, isUniqueKey, columnSortOrder, sortOrdinal);
- break;
- case SqlDbType.Udt:
- Construct(name, dbType, userDefinedType, "", useServerDefault, isUniqueKey, columnSortOrder, sortOrdinal);
- break;
- default:
- SQL.InvalidSqlDbTypeForConstructor(dbType);
- break;
- }
- }
-
- ///
- public SqlMetaData(String name, SqlDbType dbType, string database, string owningSchema, string objectName)
- {
- Construct(name, dbType, database, owningSchema, objectName, x_defaultUseServerDefault, x_defaultIsUniqueKey,
- x_defaultColumnSortOrder, x_defaultSortOrdinal);
- }
-
- // Most general constructor, should be able to initialize all SqlMetaData fields.(Used by SqlParameter)
- internal SqlMetaData(String name,
- SqlDbType sqlDBType,
- long maxLength,
- byte precision,
- byte scale,
- long localeId,
- SqlCompareOptions compareOptions,
- string xmlSchemaCollectionDatabase,
- string xmlSchemaCollectionOwningSchema,
- string xmlSchemaCollectionName,
- bool partialLength,
- Type udtType)
- {
- AssertNameIsValid(name);
-
- m_strName = name;
- m_sqlDbType = sqlDBType;
- m_lMaxLength = maxLength;
- m_bPrecision = precision;
- m_bScale = scale;
- m_lLocale = localeId;
- m_eCompareOptions = compareOptions;
- m_XmlSchemaCollectionDatabase = xmlSchemaCollectionDatabase;
- m_XmlSchemaCollectionOwningSchema = xmlSchemaCollectionOwningSchema;
- m_XmlSchemaCollectionName = xmlSchemaCollectionName;
- m_bPartialLength = partialLength;
-
- m_udttype = udtType;
- }
-
- // Private constructor used to initialize default instance array elements.
- // DO NOT EXPOSE OUTSIDE THIS CLASS! It performs no validation.
- private SqlMetaData(String name,
- SqlDbType sqlDbType,
- long maxLength,
- byte precision,
- byte scale,
- long localeId,
- SqlCompareOptions compareOptions,
- bool partialLength)
- {
-
- AssertNameIsValid(name);
-
- m_strName = name;
- m_sqlDbType = sqlDbType;
- m_lMaxLength = maxLength;
- m_bPrecision = precision;
- m_bScale = scale;
- m_lLocale = localeId;
- m_eCompareOptions = compareOptions;
- m_bPartialLength = partialLength;
- m_udttype = null;
- }
-
- ///
- public SqlCompareOptions CompareOptions
- {
- get
- {
- return m_eCompareOptions;
- }
- }
-
- ///
- public DbType DbType
- {
- get
- {
- return sxm_rgSqlDbTypeToDbType[(int)m_sqlDbType];
- }
- }
-
- ///
- public bool IsUniqueKey
- {
- get
- {
- return m_isUniqueKey;
- }
- }
-
- ///
- public long LocaleId
- {
- get
- {
- return m_lLocale;
- }
- }
-
- ///
- public static long Max
- {
- get
- {
- return x_lMax;
- }
- }
-
- ///
- public long MaxLength
- {
- get
- {
- return m_lMaxLength;
- }
- }
-
- ///
- public string Name
- {
- get
- {
- return m_strName;
- }
- }
-
- ///
- public byte Precision
- {
- get
- {
- return m_bPrecision;
- }
- }
-
- ///
- public byte Scale
- {
- get
- {
- return m_bScale;
- }
- }
-
- ///
- public SortOrder SortOrder
- {
- get
- {
- return m_columnSortOrder;
- }
- }
-
- ///
- public int SortOrdinal
- {
- get
- {
- return m_sortOrdinal;
- }
- }
-
- ///
- public SqlDbType SqlDbType
- {
- get
- {
- return m_sqlDbType;
- }
- }
-
- ///
- public Type Type
- {
- get
- {
- return m_udttype;
- }
- }
-
- ///
- public string TypeName
- {
- get
- {
- if (m_serverTypeName != null)
- {
- return m_serverTypeName;
- }
- else if (SqlDbType == SqlDbType.Udt)
- {
- return UdtTypeName;
- }
- else
- {
- return sxm_rgDefaults[(int)SqlDbType].Name;
- }
- }
- }
-
- internal string ServerTypeName
- {
- get
- {
- return m_serverTypeName;
- }
- }
-
- ///
- public bool UseServerDefault
- {
- get
- {
- return m_useServerDefault;
- }
- }
-
- ///
- public string XmlSchemaCollectionDatabase
- {
- get
- {
- return m_XmlSchemaCollectionDatabase;
- }
- }
-
- ///
- public string XmlSchemaCollectionName
- {
- get
- {
- return m_XmlSchemaCollectionName;
- }
- }
-
- ///
- public string XmlSchemaCollectionOwningSchema
- {
- get
- {
- return m_XmlSchemaCollectionOwningSchema;
- }
- }
-
- internal bool IsPartialLength
- {
- get
- {
- return m_bPartialLength;
- }
- }
-
- internal string UdtTypeName
- {
- get
- {
- if (SqlDbType != SqlDbType.Udt)
- {
- return null;
- }
- else if (m_udttype == null)
- {
- return null;
- }
- else
- {
- return m_udttype.FullName;
- }
- }
- }
-
- // Construction for all types that do not have variable attributes
- private void Construct(String name, SqlDbType dbType, bool useServerDefault,
- bool isUniqueKey, SortOrder columnSortOrder, int sortOrdinal)
- {
- AssertNameIsValid(name);
-
- ValidateSortOrder(columnSortOrder, sortOrdinal);
-
- // Check for absence of explicitly-allowed types to avoid unexpected additions when new types are added
- if (!(SqlDbType.BigInt == dbType ||
- SqlDbType.Bit == dbType ||
- SqlDbType.DateTime == dbType ||
- SqlDbType.Date == dbType ||
- SqlDbType.DateTime2 == dbType ||
- SqlDbType.DateTimeOffset == dbType ||
- SqlDbType.Decimal == dbType ||
- SqlDbType.Float == dbType ||
- SqlDbType.Image == dbType ||
- SqlDbType.Int == dbType ||
- SqlDbType.Money == dbType ||
- SqlDbType.NText == dbType ||
- SqlDbType.Real == dbType ||
- SqlDbType.SmallDateTime == dbType ||
- SqlDbType.SmallInt == dbType ||
- SqlDbType.SmallMoney == dbType ||
- SqlDbType.Text == dbType ||
- SqlDbType.Time == dbType ||
- SqlDbType.Timestamp == dbType ||
- SqlDbType.TinyInt == dbType ||
- SqlDbType.UniqueIdentifier == dbType ||
- SqlDbType.Variant == dbType ||
- SqlDbType.Xml == dbType))
- throw SQL.InvalidSqlDbTypeForConstructor(dbType);
-
- SetDefaultsForType(dbType);
-
- if (SqlDbType.NText == dbType || SqlDbType.Text == dbType)
- {
- m_lLocale = System.Globalization.CultureInfo.CurrentCulture.LCID;
- }
-
-
- m_strName = name;
- m_useServerDefault = useServerDefault;
- m_isUniqueKey = isUniqueKey;
- m_columnSortOrder = columnSortOrder;
- m_sortOrdinal = sortOrdinal;
- }
-
- // Construction for all types that vary by user-specified length (not Udts)
- private void Construct(String name, SqlDbType dbType, long maxLength, bool useServerDefault,
- bool isUniqueKey, SortOrder columnSortOrder, int sortOrdinal)
- {
- AssertNameIsValid(name);
-
- ValidateSortOrder(columnSortOrder, sortOrdinal);
-
- long lLocale = 0;
- if (SqlDbType.Char == dbType)
- {
- if (maxLength > x_lServerMaxANSI || maxLength < 0)
- throw ADP.Argument(StringsHelper.GetString(Strings.ADP_InvalidDataLength2, maxLength.ToString(CultureInfo.InvariantCulture)), "maxLength");
- lLocale = System.Globalization.CultureInfo.CurrentCulture.LCID;
- }
- else if (SqlDbType.VarChar == dbType)
- {
- if ((maxLength > x_lServerMaxANSI || maxLength < 0) && maxLength != Max)
- throw ADP.Argument(StringsHelper.GetString(Strings.ADP_InvalidDataLength2, maxLength.ToString(CultureInfo.InvariantCulture)), "maxLength");
- lLocale = System.Globalization.CultureInfo.CurrentCulture.LCID;
- }
- else if (SqlDbType.NChar == dbType)
- {
- if (maxLength > x_lServerMaxUnicode || maxLength < 0)
- throw ADP.Argument(StringsHelper.GetString(Strings.ADP_InvalidDataLength2, maxLength.ToString(CultureInfo.InvariantCulture)), "maxLength");
- lLocale = System.Globalization.CultureInfo.CurrentCulture.LCID;
- }
- else if (SqlDbType.NVarChar == dbType)
- {
- if ((maxLength > x_lServerMaxUnicode || maxLength < 0) && maxLength != Max)
- throw ADP.Argument(StringsHelper.GetString(Strings.ADP_InvalidDataLength2, maxLength.ToString(CultureInfo.InvariantCulture)), "maxLength");
- lLocale = System.Globalization.CultureInfo.CurrentCulture.LCID;
- }
- else if (SqlDbType.NText == dbType || SqlDbType.Text == dbType)
- {
- // old-style lobs only allowed with Max length
- if (SqlMetaData.Max != maxLength)
- throw ADP.Argument(StringsHelper.GetString(Strings.ADP_InvalidDataLength2, maxLength.ToString(CultureInfo.InvariantCulture)), "maxLength");
- lLocale = System.Globalization.CultureInfo.CurrentCulture.LCID;
- }
- else if (SqlDbType.Binary == dbType)
- {
- if (maxLength > x_lServerMaxBinary || maxLength < 0)
- throw ADP.Argument(StringsHelper.GetString(Strings.ADP_InvalidDataLength2, maxLength.ToString(CultureInfo.InvariantCulture)), "maxLength");
- }
- else if (SqlDbType.VarBinary == dbType)
- {
- if ((maxLength > x_lServerMaxBinary || maxLength < 0) && maxLength != Max)
- throw ADP.Argument(StringsHelper.GetString(Strings.ADP_InvalidDataLength2, maxLength.ToString(CultureInfo.InvariantCulture)), "maxLength");
- }
- else if (SqlDbType.Image == dbType)
- {
- // old-style lobs only allowed with Max length
- if (SqlMetaData.Max != maxLength)
- throw ADP.Argument(StringsHelper.GetString(Strings.ADP_InvalidDataLength2, maxLength.ToString(CultureInfo.InvariantCulture)), "maxLength");
- }
- else
- throw SQL.InvalidSqlDbTypeForConstructor(dbType);
-
- SetDefaultsForType(dbType);
-
- m_strName = name;
- m_lMaxLength = maxLength;
- m_lLocale = lLocale;
- m_useServerDefault = useServerDefault;
- m_isUniqueKey = isUniqueKey;
- m_columnSortOrder = columnSortOrder;
- m_sortOrdinal = sortOrdinal;
- }
-
- // Construction for string types with specified locale/compare options
- private void Construct(String name,
- SqlDbType dbType,
- long maxLength,
- long locale,
- SqlCompareOptions compareOptions,
- bool useServerDefault,
- bool isUniqueKey,
- SortOrder columnSortOrder,
- int sortOrdinal)
- {
- AssertNameIsValid(name);
-
- ValidateSortOrder(columnSortOrder, sortOrdinal);
-
- // Validate type and max length.
- if (SqlDbType.Char == dbType)
- {
- if (maxLength > x_lServerMaxANSI || maxLength < 0)
- throw ADP.Argument(StringsHelper.GetString(Strings.ADP_InvalidDataLength2, maxLength.ToString(CultureInfo.InvariantCulture)), "maxLength");
- }
- else if (SqlDbType.VarChar == dbType)
- {
- if ((maxLength > x_lServerMaxANSI || maxLength < 0) && maxLength != Max)
- throw ADP.Argument(StringsHelper.GetString(Strings.ADP_InvalidDataLength2, maxLength.ToString(CultureInfo.InvariantCulture)), "maxLength");
- }
- else if (SqlDbType.NChar == dbType)
- {
- if (maxLength > x_lServerMaxUnicode || maxLength < 0)
- throw ADP.Argument(StringsHelper.GetString(Strings.ADP_InvalidDataLength2, maxLength.ToString(CultureInfo.InvariantCulture)), "maxLength");
- }
- else if (SqlDbType.NVarChar == dbType)
- {
- if ((maxLength > x_lServerMaxUnicode || maxLength < 0) && maxLength != Max)
- throw ADP.Argument(StringsHelper.GetString(Strings.ADP_InvalidDataLength2, maxLength.ToString(CultureInfo.InvariantCulture)), "maxLength");
- }
- else if (SqlDbType.NText == dbType || SqlDbType.Text == dbType)
- {
- // old-style lobs only allowed with Max length
- if (SqlMetaData.Max != maxLength)
- throw ADP.Argument(StringsHelper.GetString(Strings.ADP_InvalidDataLength2, maxLength.ToString(CultureInfo.InvariantCulture)), "maxLength");
- }
- else
- throw SQL.InvalidSqlDbTypeForConstructor(dbType);
-
- // Validate locale?
-
- // Validate compare options
- // Binary sort must be by itself.
- // Nothing else but the Ignore bits is allowed.
- if (SqlCompareOptions.BinarySort != compareOptions &&
- 0 != (~((int)SqlCompareOptions.IgnoreCase | (int)SqlCompareOptions.IgnoreNonSpace |
- (int)SqlCompareOptions.IgnoreKanaType | (int)SqlCompareOptions.IgnoreWidth) &
- (int)compareOptions))
- throw ADP.InvalidEnumerationValue(typeof(SqlCompareOptions), (int)compareOptions);
-
- SetDefaultsForType(dbType);
-
- m_strName = name;
- m_lMaxLength = maxLength;
- m_lLocale = locale;
- m_eCompareOptions = compareOptions;
- m_useServerDefault = useServerDefault;
- m_isUniqueKey = isUniqueKey;
- m_columnSortOrder = columnSortOrder;
- m_sortOrdinal = sortOrdinal;
- }
-
-
- private static byte[] __maxLenFromPrecision = new byte[] {5,5,5,5,5,5,5,5,5,9,9,9,9,9,
- 9,9,9,9,9,13,13,13,13,13,13,13,13,13,17,17,17,17,17,17,17,17,17,17};
-
- private const byte MaxTimeScale = 7;
-
- private static byte[] __maxVarTimeLenOffsetFromScale = new byte[] { 2, 2, 2, 1, 1, 0, 0, 0 };
-
- // Construction for Decimal type and new Katmai Date/Time types
- private void Construct(String name, SqlDbType dbType, byte precision, byte scale, bool useServerDefault,
- bool isUniqueKey, SortOrder columnSortOrder, int sortOrdinal)
- {
- AssertNameIsValid(name);
-
- ValidateSortOrder(columnSortOrder, sortOrdinal);
-
- if (SqlDbType.Decimal == dbType)
- {
- if (precision > SqlDecimal.MaxPrecision || scale > precision)
- throw SQL.PrecisionValueOutOfRange(precision);
-
- if (scale > SqlDecimal.MaxScale)
- throw SQL.ScaleValueOutOfRange(scale);
- }
- else if (SqlDbType.Time == dbType || SqlDbType.DateTime2 == dbType || SqlDbType.DateTimeOffset == dbType)
- {
- if (scale > MaxTimeScale)
- {
- throw SQL.TimeScaleValueOutOfRange(scale);
- }
- }
- else
- {
- throw SQL.InvalidSqlDbTypeForConstructor(dbType);
- }
- SetDefaultsForType(dbType);
-
- m_strName = name;
- m_bPrecision = precision;
- m_bScale = scale;
- if (SqlDbType.Decimal == dbType)
- {
- m_lMaxLength = __maxLenFromPrecision[precision - 1];
- }
- else
- {
- m_lMaxLength -= __maxVarTimeLenOffsetFromScale[scale];
- }
- m_useServerDefault = useServerDefault;
- m_isUniqueKey = isUniqueKey;
- m_columnSortOrder = columnSortOrder;
- m_sortOrdinal = sortOrdinal;
- }
-
- // Construction for Udt type
- private void Construct(String name, SqlDbType dbType, Type userDefinedType, string serverTypeName, bool useServerDefault,
- bool isUniqueKey, SortOrder columnSortOrder, int sortOrdinal)
- {
- AssertNameIsValid(name);
-
- ValidateSortOrder(columnSortOrder, sortOrdinal);
-
- if (SqlDbType.Udt != dbType)
- throw SQL.InvalidSqlDbTypeForConstructor(dbType);
-
- if (null == userDefinedType)
- throw ADP.ArgumentNull("userDefinedType");
-
- SetDefaultsForType(SqlDbType.Udt);
-
- m_strName = name;
- m_lMaxLength = SerializationHelperSql9.GetUdtMaxLength(userDefinedType);
- m_udttype = userDefinedType;
- m_serverTypeName = serverTypeName;
- m_useServerDefault = useServerDefault;
- m_isUniqueKey = isUniqueKey;
- m_columnSortOrder = columnSortOrder;
- m_sortOrdinal = sortOrdinal;
- }
-
- // Construction for Xml type
- private void Construct(String name, SqlDbType dbType, string database, string owningSchema,
- string objectName, bool useServerDefault, bool isUniqueKey, SortOrder columnSortOrder,
- int sortOrdinal)
- {
- AssertNameIsValid(name);
-
- ValidateSortOrder(columnSortOrder, sortOrdinal);
-
- if (SqlDbType.Xml != dbType)
- throw SQL.InvalidSqlDbTypeForConstructor(dbType);
-
- if (null != database || null != owningSchema)
- {
- if (null == objectName)
- {
- throw ADP.ArgumentNull("objectName");
- }
- }
-
- SetDefaultsForType(SqlDbType.Xml);
- m_strName = name;
-
- m_XmlSchemaCollectionDatabase = database;
- m_XmlSchemaCollectionOwningSchema = owningSchema;
- m_XmlSchemaCollectionName = objectName;
- m_useServerDefault = useServerDefault;
- m_isUniqueKey = isUniqueKey;
- m_columnSortOrder = columnSortOrder;
- m_sortOrdinal = sortOrdinal;
- }
-
- private void AssertNameIsValid(string name)
- {
- if (null == name)
- throw ADP.ArgumentNull("name");
-
- if (Microsoft.Data.SqlClient.Server.SmiMetaData.MaxNameLength < name.Length)
- throw SQL.NameTooLong("name");
- }
-
- private void ValidateSortOrder(SortOrder columnSortOrder, int sortOrdinal)
- {
- // Check that sort order is valid enum value.
- if (SortOrder.Unspecified != columnSortOrder &&
- SortOrder.Ascending != columnSortOrder &&
- SortOrder.Descending != columnSortOrder)
- {
- throw SQL.InvalidSortOrder(columnSortOrder);
- }
-
- // Must specify both sort order and ordinal, or neither
- if ((SortOrder.Unspecified == columnSortOrder) != (x_defaultSortOrdinal == sortOrdinal))
- {
- throw SQL.MustSpecifyBothSortOrderAndOrdinal(columnSortOrder, sortOrdinal);
- }
- }
-
- ///
- public Int16 Adjust(Int16 value)
- {
- if (SqlDbType.SmallInt != SqlDbType)
- ThrowInvalidType();
- return value;
- }
-
- ///
- public Int32 Adjust(Int32 value)
- {
- if (SqlDbType.Int != SqlDbType)
- ThrowInvalidType();
- return value;
- }
-
- ///
- public Int64 Adjust(Int64 value)
- {
- if (SqlDbType.BigInt != SqlDbType)
- ThrowInvalidType();
- return value;
- }
-
- ///
- public float Adjust(float value)
- {
- if (SqlDbType.Real != SqlDbType)
- ThrowInvalidType();
- return value;
- }
-
- ///
- public double Adjust(double value)
- {
- if (SqlDbType.Float != SqlDbType)
- ThrowInvalidType();
- return value;
- }
-
- ///
- public string Adjust(string value)
- {
- if (SqlDbType.Char == SqlDbType || SqlDbType.NChar == SqlDbType)
- {
- //DBG.Assert(Max!=MaxLength, "SqlMetaData.Adjust(string): Fixed-length type with Max length!");
- // Don't pad null values
- if (null != value)
- {
- // Pad if necessary
- if (value.Length < MaxLength)
- value = value.PadRight((int)MaxLength);
- }
- }
- else if (SqlDbType.VarChar != SqlDbType &&
- SqlDbType.NVarChar != SqlDbType &&
- SqlDbType.Text != SqlDbType &&
- SqlDbType.NText != SqlDbType)
- {
- ThrowInvalidType();
- }
-
- // Handle null values after type check
- if (null == value)
- {
- return null;
- }
-
- if (value.Length > MaxLength && Max != MaxLength)
- value = value.Remove((int)MaxLength, (int)(value.Length - MaxLength));
-
- return value;
- }
-
- ///
- public decimal Adjust(decimal value)
- {
- if (SqlDbType.Decimal != SqlDbType &&
- SqlDbType.Money != SqlDbType &&
- SqlDbType.SmallMoney != SqlDbType)
- {
- ThrowInvalidType();
- }
-
- if (SqlDbType.Decimal != SqlDbType)
- {
- VerifyMoneyRange(new SqlMoney(value));
- return value;
- }
- else
- {
- SqlDecimal sdValue = InternalAdjustSqlDecimal(new SqlDecimal(value));
- return sdValue.Value;
- }
- }
-
- ///
- public DateTime Adjust(DateTime value)
- {
- if (SqlDbType.DateTime == SqlDbType || SqlDbType.SmallDateTime == SqlDbType)
- {
- VerifyDateTimeRange(value);
- }
- else if (SqlDbType.DateTime2 == SqlDbType)
- {
- return new DateTime(InternalAdjustTimeTicks(value.Ticks));
- }
- else if (SqlDbType.Date == SqlDbType)
- {
- return value.Date;
- }
- else
- {
- ThrowInvalidType();
- }
- return value;
- }
-
- ///
- public Guid Adjust(Guid value)
- {
- if (SqlDbType.UniqueIdentifier != SqlDbType)
- ThrowInvalidType();
- return value;
- }
-
- ///
- public SqlBoolean Adjust(SqlBoolean value)
- {
- if (SqlDbType.Bit != SqlDbType)
- ThrowInvalidType();
- return value;
- }
-
- ///
- public SqlByte Adjust(SqlByte value)
- {
- if (SqlDbType.TinyInt != SqlDbType)
- ThrowInvalidType();
- return value;
- }
-
- ///
- public SqlInt16 Adjust(SqlInt16 value)
- {
- if (SqlDbType.SmallInt != SqlDbType)
- ThrowInvalidType();
- return value;
- }
-
- ///
- public SqlInt32 Adjust(SqlInt32 value)
- {
- if (SqlDbType.Int != SqlDbType)
- ThrowInvalidType();
- return value;
- }
-
- ///
- public SqlInt64 Adjust(SqlInt64 value)
- {
- if (SqlDbType.BigInt != SqlDbType)
- ThrowInvalidType();
- return value;
- }
-
- ///
- public SqlSingle Adjust(SqlSingle value)
- {
- if (SqlDbType.Real != SqlDbType)
- ThrowInvalidType();
- return value;
- }
-
- ///
- public SqlDouble Adjust(SqlDouble value)
- {
- if (SqlDbType.Float != SqlDbType)
- ThrowInvalidType();
- return value;
- }
-
- ///
- public SqlMoney Adjust(SqlMoney value)
- {
- if (SqlDbType.Money != SqlDbType &&
- SqlDbType.SmallMoney != SqlDbType)
- ThrowInvalidType();
-
- if (!value.IsNull)
- VerifyMoneyRange(value);
-
- return value;
- }
-
- ///
- public SqlDateTime Adjust(SqlDateTime value)
- {
- if (SqlDbType.DateTime != SqlDbType &&
- SqlDbType.SmallDateTime != SqlDbType)
- ThrowInvalidType();
-
- if (!value.IsNull)
- VerifyDateTimeRange(value.Value);
-
- return value;
- }
-
- ///
- public SqlDecimal Adjust(SqlDecimal value)
- {
- if (SqlDbType.Decimal != SqlDbType)
- ThrowInvalidType();
- return InternalAdjustSqlDecimal(value);
- }
-
- ///
- public SqlString Adjust(SqlString value)
- {
- if (SqlDbType.Char == SqlDbType || SqlDbType.NChar == SqlDbType)
- {
- //DBG.Assert(Max!=MaxLength, "SqlMetaData.Adjust(SqlString): Fixed-length type with Max length!");
- // Don't pad null values
- if (!value.IsNull)
- {
- // Pad fixed-length types
- if (value.Value.Length < MaxLength)
- return new SqlString(value.Value.PadRight((int)MaxLength));
- }
- }
- else if (SqlDbType.VarChar != SqlDbType && SqlDbType.NVarChar != SqlDbType &&
- SqlDbType.Text != SqlDbType && SqlDbType.NText != SqlDbType)
- ThrowInvalidType();
-
- // Handle null values after type check
- if (value.IsNull)
- {
- return value;
- }
-
- // trim all types
- if (value.Value.Length > MaxLength && Max != MaxLength)
- value = new SqlString(value.Value.Remove((int)MaxLength, (int)(value.Value.Length - MaxLength)));
-
- return value;
- }
-
- ///
- public SqlBinary Adjust(SqlBinary value)
- {
- if (SqlDbType.Binary == SqlDbType ||
- SqlDbType.Timestamp == SqlDbType)
- {
- if (!value.IsNull)
- {
- // Pad fixed-length types
- if (value.Length < MaxLength)
- {
- byte[] rgbValue = value.Value;
- byte[] rgbNewValue = new byte[MaxLength];
- Array.Copy(rgbValue, rgbNewValue, rgbValue.Length);
- Array.Clear(rgbNewValue, rgbValue.Length, rgbNewValue.Length - rgbValue.Length);
- return new SqlBinary(rgbNewValue);
- }
- }
- }
- else if (SqlDbType.VarBinary != SqlDbType &&
- SqlDbType.Image != SqlDbType)
- ThrowInvalidType();
-
- // Handle null values
- if (value.IsNull)
- {
- return value;
- }
-
- // trim all types
- if (value.Length > MaxLength && Max != MaxLength)
- {
- byte[] rgbValue = value.Value;
- byte[] rgbNewValue = new byte[MaxLength];
- Array.Copy(rgbValue, rgbNewValue, (int)MaxLength);
- value = new SqlBinary(rgbNewValue);
- }
-
- return value;
- }
-
- ///
- public SqlGuid Adjust(SqlGuid value)
- {
- if (SqlDbType.UniqueIdentifier != SqlDbType)
- ThrowInvalidType();
- return value;
- }
-
- ///
- public SqlChars Adjust(SqlChars value)
- {
- if (SqlDbType.Char == SqlDbType || SqlDbType.NChar == SqlDbType)
- {
- //DBG.Assert(Max!=MaxLength, "SqlMetaData.Adjust(SqlChars): Fixed-length type with Max length!");
- // Don't pad null values
- if (null != value && !value.IsNull)
- {
- // Pad fixed-length types
- long oldLength = value.Length;
- if (oldLength < MaxLength)
- {
- // Make sure buffer is long enough
- if (value.MaxLength < MaxLength)
- {
- char[] rgchNew = new char[(int)MaxLength];
- Array.Copy(value.Buffer, rgchNew, (int)oldLength);
- value = new SqlChars(rgchNew);
- }
-
- // pad extra space
- char[] rgchTemp = value.Buffer;
- for (long i = oldLength; i < MaxLength; i++)
- rgchTemp[i] = ' ';
-
- value.SetLength(MaxLength);
- return value;
- }
- }
- }
- else if (SqlDbType.VarChar != SqlDbType && SqlDbType.NVarChar != SqlDbType &&
- SqlDbType.Text != SqlDbType && SqlDbType.NText != SqlDbType)
- ThrowInvalidType();
-
- // Handle null values after type check.
- if (null == value || value.IsNull)
- {
- return value;
- }
-
- // trim all types
- if (value.Length > MaxLength && Max != MaxLength)
- value.SetLength(MaxLength);
-
- return value;
- }
-
- ///
- public SqlBytes Adjust(SqlBytes value)
- {
- if (SqlDbType.Binary == SqlDbType || SqlDbType.Timestamp == SqlDbType)
- {
- //DBG.Assert(Max!=MaxLength, "SqlMetaData.Adjust(SqlBytes): Fixed-length type with Max length!");
- // Don't pad null values
- if (null != value && !value.IsNull)
- {
- // Pad fixed-length types
- int oldLength = (int)value.Length;
- if (oldLength < MaxLength)
- {
- // Make sure buffer is long enough
- if (value.MaxLength < MaxLength)
- {
- byte[] rgbNew = new byte[MaxLength];
- Array.Copy(value.Buffer, rgbNew, (int)oldLength);
- value = new SqlBytes(rgbNew);
- }
-
- // pad extra space
- byte[] rgbTemp = value.Buffer;
- Array.Clear(rgbTemp, oldLength, rgbTemp.Length - oldLength);
- value.SetLength(MaxLength);
- return value;
- }
- }
- }
- else if (SqlDbType.VarBinary != SqlDbType &&
- SqlDbType.Image != SqlDbType)
- ThrowInvalidType();
-
- // Handle null values after type check.
- if (null == value || value.IsNull)
- {
- return value;
- }
-
- // trim all types
- if (value.Length > MaxLength && Max != MaxLength)
- value.SetLength(MaxLength);
-
- return value;
- }
-
- ///
- public SqlXml Adjust(SqlXml value)
- {
- if (SqlDbType.Xml != SqlDbType)
- ThrowInvalidType();
- return value;
- }
-
- ///
- public TimeSpan Adjust(TimeSpan value)
- {
- if (SqlDbType.Time != SqlDbType)
- ThrowInvalidType();
- VerifyTimeRange(value);
- return new TimeSpan(InternalAdjustTimeTicks(value.Ticks));
- }
-
- ///
- public DateTimeOffset Adjust(DateTimeOffset value)
- {
- if (SqlDbType.DateTimeOffset != SqlDbType)
- ThrowInvalidType();
- return new DateTimeOffset(InternalAdjustTimeTicks(value.Ticks), value.Offset);
- }
-
- ///
- public object Adjust(object value)
- {
- // Pass null references through
- if (null == value)
- return null;
-
- Type dataType = value.GetType();
- switch (Type.GetTypeCode(dataType))
- {
- case TypeCode.Boolean:
- value = this.Adjust((Boolean)value);
- break;
- case TypeCode.Byte:
- value = this.Adjust((Byte)value);
- break;
- case TypeCode.Char:
- value = this.Adjust((Char)value);
- break;
- case TypeCode.DateTime:
- value = this.Adjust((DateTime)value);
- break;
- case TypeCode.DBNull: /* DBNull passes through as is for all types */
- break;
- case TypeCode.Decimal:
- value = this.Adjust((Decimal)value);
- break;
- case TypeCode.Double:
- value = this.Adjust((Double)value);
- break;
- case TypeCode.Empty:
- throw ADP.InvalidDataType(TypeCode.Empty);
- case TypeCode.Int16:
- value = this.Adjust((Int16)value);
- break;
- case TypeCode.Int32:
- value = this.Adjust((Int32)value);
- break;
- case TypeCode.Int64:
- value = this.Adjust((Int64)value);
- break;
- case TypeCode.SByte:
- throw ADP.InvalidDataType(TypeCode.SByte);
- case TypeCode.Single:
- value = this.Adjust((Single)value);
- break;
- case TypeCode.String:
- value = this.Adjust((String)value);
- break;
- case TypeCode.UInt16:
- throw ADP.InvalidDataType(TypeCode.UInt16);
- case TypeCode.UInt32:
- throw ADP.InvalidDataType(TypeCode.UInt32);
- case TypeCode.UInt64:
- throw ADP.InvalidDataType(TypeCode.UInt64);
- case TypeCode.Object:
- if (dataType == typeof(System.Byte[]))
- value = this.Adjust((System.Byte[])value);
- else if (dataType == typeof(System.Char[]))
- value = this.Adjust((System.Char[])value);
- else if (dataType == typeof(System.Guid))
- value = this.Adjust((System.Guid)value);
- else if (dataType == typeof(System.Object))
- {
- //
- throw ADP.InvalidDataType(TypeCode.UInt64);
- }
- else if (dataType == typeof(SqlBinary))
- value = this.Adjust((SqlBinary)value);
- else if (dataType == typeof(SqlBoolean))
- value = this.Adjust((SqlBoolean)value);
- else if (dataType == typeof(SqlByte))
- value = this.Adjust((SqlByte)value);
- else if (dataType == typeof(SqlDateTime))
- value = this.Adjust((SqlDateTime)value);
- else if (dataType == typeof(SqlDouble))
- value = this.Adjust((SqlDouble)value);
- else if (dataType == typeof(SqlGuid))
- value = this.Adjust((SqlGuid)value);
- else if (dataType == typeof(SqlInt16))
- value = this.Adjust((SqlInt16)value);
- else if (dataType == typeof(SqlInt32))
- value = this.Adjust((SqlInt32)value);
- else if (dataType == typeof(SqlInt64))
- value = this.Adjust((SqlInt64)value);
- else if (dataType == typeof(SqlMoney))
- value = this.Adjust((SqlMoney)value);
- else if (dataType == typeof(SqlDecimal))
- value = this.Adjust((SqlDecimal)value);
- else if (dataType == typeof(SqlSingle))
- value = this.Adjust((SqlSingle)value);
- else if (dataType == typeof(SqlString))
- value = this.Adjust((SqlString)value);
- else if (dataType == typeof(SqlChars))
- value = this.Adjust((SqlChars)value);
- else if (dataType == typeof(SqlBytes))
- value = this.Adjust((SqlBytes)value);
- else if (dataType == typeof(SqlXml))
- value = this.Adjust((SqlXml)value);
- else if (dataType == typeof(TimeSpan))
- value = this.Adjust((TimeSpan)value);
- else if (dataType == typeof(DateTimeOffset))
- value = this.Adjust((DateTimeOffset)value);
- else
- {
- // Handle UDTs?
- throw ADP.UnknownDataType(dataType);
- }
- break;
-
-
- default:
- throw ADP.UnknownDataTypeCode(dataType, Type.GetTypeCode(dataType));
- }
-
- return value;
- }
-
- ///
- public static SqlMetaData InferFromValue(object value, String name)
- {
- if (value == null)
- throw ADP.ArgumentNull("value");
- SqlMetaData smd = null;
- Type dataType = value.GetType();
- switch (Type.GetTypeCode(dataType))
- {
- case TypeCode.Boolean:
- smd = new SqlMetaData(name, SqlDbType.Bit);
- break;
- case TypeCode.Byte:
- smd = new SqlMetaData(name, SqlDbType.TinyInt);
- break;
- case TypeCode.Char:
- smd = new SqlMetaData(name, SqlDbType.NVarChar, 1);
- break;
- case TypeCode.DateTime:
- smd = new SqlMetaData(name, SqlDbType.DateTime);
- break;
- case TypeCode.DBNull:
- throw ADP.InvalidDataType(TypeCode.DBNull);
- case TypeCode.Decimal:
- { // Add brackets in order to contain scope declare local variable "sd"
- // use logic inside SqlDecimal to infer precision and scale.
- SqlDecimal sd = new SqlDecimal((Decimal)value);
- smd = new SqlMetaData(name, SqlDbType.Decimal, sd.Precision, sd.Scale);
- }
- break;
- case TypeCode.Double:
- smd = new SqlMetaData(name, SqlDbType.Float);
- break;
- case TypeCode.Empty:
- throw ADP.InvalidDataType(TypeCode.Empty);
- case TypeCode.Int16:
- smd = new SqlMetaData(name, SqlDbType.SmallInt);
- break;
- case TypeCode.Int32:
- smd = new SqlMetaData(name, SqlDbType.Int);
- break;
- case TypeCode.Int64:
- smd = new SqlMetaData(name, SqlDbType.BigInt);
- break;
- case TypeCode.SByte:
- throw ADP.InvalidDataType(TypeCode.SByte);
- case TypeCode.Single:
- smd = new SqlMetaData(name, SqlDbType.Real);
- break;
- case TypeCode.String:
- {
- long maxLen = ((String)value).Length;
- if (maxLen < 1)
- maxLen = 1;
-
- if (x_lServerMaxUnicode < maxLen)
- maxLen = Max;
-
- smd = new SqlMetaData(name, SqlDbType.NVarChar, maxLen);
- }
- break;
- case TypeCode.UInt16:
- throw ADP.InvalidDataType(TypeCode.UInt16);
- case TypeCode.UInt32:
- throw ADP.InvalidDataType(TypeCode.UInt32);
- case TypeCode.UInt64:
- throw ADP.InvalidDataType(TypeCode.UInt64);
- case TypeCode.Object:
- if (dataType == typeof(System.Byte[]))
- {
- long maxLen = ((System.Byte[])value).Length;
- if (maxLen < 1)
- maxLen = 1;
-
- if (x_lServerMaxBinary < maxLen)
- maxLen = Max;
-
- smd = new SqlMetaData(name, SqlDbType.VarBinary, maxLen);
- }
- else if (dataType == typeof(System.Char[]))
- {
- long maxLen = ((System.Char[])value).Length;
- if (maxLen < 1)
- maxLen = 1;
-
- if (x_lServerMaxUnicode < maxLen)
- maxLen = Max;
-
- smd = new SqlMetaData(name, SqlDbType.NVarChar, maxLen);
- }
- else if (dataType == typeof(System.Guid))
- smd = new SqlMetaData(name, SqlDbType.UniqueIdentifier);
- else if (dataType == typeof(System.Object))
- smd = new SqlMetaData(name, SqlDbType.Variant);
- else if (dataType == typeof(SqlBinary))
- {
- long maxLen;
- SqlBinary sb = ((SqlBinary)value);
- if (!sb.IsNull)
- {
- maxLen = sb.Length;
- if (maxLen < 1)
- maxLen = 1;
-
- if (x_lServerMaxBinary < maxLen)
- maxLen = Max;
- }
- else
- maxLen = sxm_rgDefaults[(int)SqlDbType.VarBinary].MaxLength;
-
- smd = new SqlMetaData(name, SqlDbType.VarBinary, maxLen);
- }
- else if (dataType == typeof(SqlBoolean))
- smd = new SqlMetaData(name, SqlDbType.Bit);
- else if (dataType == typeof(SqlByte))
- smd = new SqlMetaData(name, SqlDbType.TinyInt);
- else if (dataType == typeof(SqlDateTime))
- smd = new SqlMetaData(name, SqlDbType.DateTime);
- else if (dataType == typeof(SqlDouble))
- smd = new SqlMetaData(name, SqlDbType.Float);
- else if (dataType == typeof(SqlGuid))
- smd = new SqlMetaData(name, SqlDbType.UniqueIdentifier);
- else if (dataType == typeof(SqlInt16))
- smd = new SqlMetaData(name, SqlDbType.SmallInt);
- else if (dataType == typeof(SqlInt32))
- smd = new SqlMetaData(name, SqlDbType.Int);
- else if (dataType == typeof(SqlInt64))
- smd = new SqlMetaData(name, SqlDbType.BigInt);
- else if (dataType == typeof(SqlMoney))
- smd = new SqlMetaData(name, SqlDbType.Money);
- else if (dataType == typeof(SqlDecimal))
- {
- byte bPrec;
- byte scale;
- SqlDecimal sd = (SqlDecimal)value;
- if (!sd.IsNull)
- {
- bPrec = sd.Precision;
- scale = sd.Scale;
- }
- else
- {
- bPrec = sxm_rgDefaults[(int)SqlDbType.Decimal].Precision;
- scale = sxm_rgDefaults[(int)SqlDbType.Decimal].Scale;
- }
- smd = new SqlMetaData(name, SqlDbType.Decimal, bPrec, scale);
- }
- else if (dataType == typeof(SqlSingle))
- smd = new SqlMetaData(name, SqlDbType.Real);
- else if (dataType == typeof(SqlString))
- {
- SqlString ss = (SqlString)value;
- if (!ss.IsNull)
- {
- long maxLen = ss.Value.Length;
- if (maxLen < 1)
- maxLen = 1;
-
- if (maxLen > x_lServerMaxUnicode)
- maxLen = Max;
-
- smd = new SqlMetaData(name, SqlDbType.NVarChar, maxLen, ss.LCID, ss.SqlCompareOptions);
- }
- else
- {
- smd = new SqlMetaData(name, SqlDbType.NVarChar, sxm_rgDefaults[(int)SqlDbType.NVarChar].MaxLength);
- }
- }
- else if (dataType == typeof(SqlChars))
- {
- long maxLen;
- SqlChars sch = (SqlChars)value;
- if (!sch.IsNull)
- {
- maxLen = sch.Length;
- if (maxLen < 1)
- maxLen = 1;
-
- if (maxLen > x_lServerMaxUnicode)
- maxLen = Max;
- }
- else
- maxLen = sxm_rgDefaults[(int)SqlDbType.NVarChar].MaxLength;
-
- smd = new SqlMetaData(name, SqlDbType.NVarChar, maxLen);
- }
- else if (dataType == typeof(SqlBytes))
- {
- long maxLen;
- SqlBytes sb = (SqlBytes)value;
- if (!sb.IsNull)
- {
- maxLen = sb.Length;
- if (maxLen < 1)
- maxLen = 1;
- else if (x_lServerMaxBinary < maxLen)
- maxLen = Max;
- }
- else
- maxLen = sxm_rgDefaults[(int)SqlDbType.VarBinary].MaxLength;
-
- smd = new SqlMetaData(name, SqlDbType.VarBinary, maxLen);
- }
- else if (dataType == typeof(SqlXml))
- smd = new SqlMetaData(name, SqlDbType.Xml);
- else if (dataType == typeof(TimeSpan))
- smd = new SqlMetaData(name, SqlDbType.Time, 0, InferScaleFromTimeTicks(((TimeSpan)value).Ticks));
- else if (dataType == typeof(DateTimeOffset))
- smd = new SqlMetaData(name, SqlDbType.DateTimeOffset, 0, InferScaleFromTimeTicks(((DateTimeOffset)value).Ticks));
- else
- throw ADP.UnknownDataType(dataType);
- break;
-
-
- default:
- throw ADP.UnknownDataTypeCode(dataType, Type.GetTypeCode(dataType));
- }
-
- return smd;
- }
-
- ///
- public bool Adjust(bool value)
- {
- if (SqlDbType.Bit != SqlDbType)
- ThrowInvalidType();
- return value;
- }
-
- ///
- public byte Adjust(byte value)
- {
- if (SqlDbType.TinyInt != SqlDbType)
- ThrowInvalidType();
- return value;
- }
-
- ///
- public byte[] Adjust(byte[] value)
- {
- if (SqlDbType.Binary == SqlDbType || SqlDbType.Timestamp == SqlDbType)
- {
- //DBG.Assert(Max!=MaxLength, "SqlMetaData.Adjust(byte[]): Fixed-length type with Max length!");
- // Don't pad null values
- if (null != value)
- {
- // Pad fixed-length types
- if (value.Length < MaxLength)
- {
- byte[] rgbNewValue = new byte[MaxLength];
- Array.Copy(value, rgbNewValue, value.Length);
- Array.Clear(rgbNewValue, value.Length, (int)rgbNewValue.Length - value.Length);
- return rgbNewValue;
- }
- }
- }
- else if (SqlDbType.VarBinary != SqlDbType &&
- SqlDbType.Image != SqlDbType)
- ThrowInvalidType();
-
- // Handle null values after type check
- if (null == value)
- {
- return null;
- }
-
- // trim all types
- if (value.Length > MaxLength && Max != MaxLength)
- {
- byte[] rgbNewValue = new byte[MaxLength];
- Array.Copy(value, rgbNewValue, (int)MaxLength);
- value = rgbNewValue;
- }
-
- return value;
- }
-
- ///
- public char Adjust(char value)
- {
- if (SqlDbType.Char == SqlDbType || SqlDbType.NChar == SqlDbType)
- {
- if (1 != MaxLength)
- ThrowInvalidType();
- }
- else if ((1 > MaxLength) || // char must have max length of at least 1
- (SqlDbType.VarChar != SqlDbType && SqlDbType.NVarChar != SqlDbType &&
- SqlDbType.Text != SqlDbType && SqlDbType.NText != SqlDbType)
- )
- ThrowInvalidType();
-
- return value;
- }
-
- ///
- public char[] Adjust(char[] value)
- {
- if (SqlDbType.Char == SqlDbType || SqlDbType.NChar == SqlDbType)
- {
- //DBG.Assert(Max!=MaxLength, "SqlMetaData.Adjust(byte[]): Fixed-length type with Max length!");
- // Don't pad null values
- if (null != value)
- {
- // Pad fixed-length types
- long oldLength = value.Length;
- if (oldLength < MaxLength)
- {
- char[] rgchNew = new char[(int)MaxLength];
- Array.Copy(value, rgchNew, (int)oldLength);
-
- // pad extra space
- for (long i = oldLength; i < rgchNew.Length; i++)
- rgchNew[i] = ' ';
-
- return rgchNew;
- }
- }
- }
- else if (SqlDbType.VarChar != SqlDbType && SqlDbType.NVarChar != SqlDbType &&
- SqlDbType.Text != SqlDbType && SqlDbType.NText != SqlDbType)
- ThrowInvalidType();
-
- // Handle null values after type check
- if (null == value)
- {
- return null;
- }
-
- // trim all types
- if (value.Length > MaxLength && Max != MaxLength)
- {
- char[] rgchNewValue = new char[MaxLength];
- Array.Copy(value, rgchNewValue, (int)MaxLength);
- value = rgchNewValue;
- }
-
-
- return value;
- }
-
-
- internal static SqlMetaData GetPartialLengthMetaData(SqlMetaData md)
- {
- if (md.IsPartialLength == true)
- {
- return md;
- }
- if (md.SqlDbType == SqlDbType.Xml)
- ThrowInvalidType(); //Xml should always have IsPartialLength = true
-
- if (md.SqlDbType == SqlDbType.NVarChar || md.SqlDbType == SqlDbType.VarChar ||
- md.SqlDbType == SqlDbType.VarBinary)
- {
- SqlMetaData mdnew = new SqlMetaData(md.Name, md.SqlDbType, SqlMetaData.Max, 0, 0, md.LocaleId,
- md.CompareOptions, null, null, null, true, md.Type);
- return mdnew;
- }
- else
- return md;
- }
-
-
- private static void ThrowInvalidType()
- {
- throw ADP.InvalidMetaDataValue();
- }
-
- // Hard coding smalldatetime limits...
- private static readonly DateTime x_dtSmallMax = new DateTime(2079, 06, 06, 23, 59, 29, 998);
- private static readonly DateTime x_dtSmallMin = new DateTime(1899, 12, 31, 23, 59, 29, 999);
- void VerifyDateTimeRange(DateTime value)
- {
- if (SqlDbType.SmallDateTime == SqlDbType && (x_dtSmallMax < value || x_dtSmallMin > value))
- ThrowInvalidType();
- }
-
- private static readonly SqlMoney x_smSmallMax = new SqlMoney(((Decimal)Int32.MaxValue) / 10000);
- private static readonly SqlMoney x_smSmallMin = new SqlMoney(((Decimal)Int32.MinValue) / 10000);
- void VerifyMoneyRange(SqlMoney value)
- {
- if (SqlDbType.SmallMoney == SqlDbType && ((x_smSmallMax < value).Value || (x_smSmallMin > value).Value))
- ThrowInvalidType();
- }
-
- private SqlDecimal InternalAdjustSqlDecimal(SqlDecimal value)
- {
- if (!value.IsNull && (value.Precision != Precision || value.Scale != Scale))
- {
- // SQLBU 402377 Force truncation if target scale is smaller than actual scale.
- if (value.Scale != Scale)
- {
- value = SqlDecimal.AdjustScale(value, Scale - value.Scale, false /* Don't round, truncate. */);
- }
- return SqlDecimal.ConvertToPrecScale(value, Precision, Scale);
- }
-
- return value;
- }
-
- private static readonly TimeSpan x_timeMin = TimeSpan.Zero;
- private static readonly TimeSpan x_timeMax = new TimeSpan(TimeSpan.TicksPerDay - 1);
- private void VerifyTimeRange(TimeSpan value)
- {
- if (SqlDbType.Time == SqlDbType && (x_timeMin > value || value > x_timeMax))
- {
- ThrowInvalidType();
- }
- }
-
- private static readonly Int64[] __unitTicksFromScale = {
- 10000000,
- 1000000,
- 100000,
- 10000,
- 1000,
- 100,
- 10,
- 1,
- };
-
- private Int64 InternalAdjustTimeTicks(Int64 ticks)
- {
- return (ticks / __unitTicksFromScale[Scale] * __unitTicksFromScale[Scale]);
- }
-
- private static byte InferScaleFromTimeTicks(Int64 ticks)
- {
- for (byte scale = 0; scale < MaxTimeScale; ++scale)
- {
- if ((ticks / __unitTicksFromScale[scale] * __unitTicksFromScale[scale]) == ticks)
- {
- return scale;
- }
- }
- return MaxTimeScale;
- }
-
- private static DbType[] sxm_rgSqlDbTypeToDbType = {
- DbType.Int64, // SqlDbType.BigInt
- DbType.Binary, // SqlDbType.Binary
- DbType.Boolean, // SqlDbType.Bit
- DbType.AnsiString, // SqlDbType.Char
- DbType.DateTime, // SqlDbType.DateTime
- DbType.Decimal, // SqlDbType.Decimal
- DbType.Double, // SqlDbType.Float
- DbType.Binary, // SqlDbType.Image
- DbType.Int32, // SqlDbType.Int
- DbType.Currency, // SqlDbType.Money
- DbType.String, // SqlDbType.NChar
- DbType.String, // SqlDbType.NText
- DbType.String, // SqlDbType.NVarChar
- DbType.Single, // SqlDbType.Real
- DbType.Guid, // SqlDbType.UniqueIdentifier
- DbType.DateTime, // SqlDbType.SmallDateTime
- DbType.Int16, // SqlDbType.SmallInt
- DbType.Currency, // SqlDbType.SmallMoney
- DbType.AnsiString, // SqlDbType.Text
- DbType.Binary, // SqlDbType.Timestamp
- DbType.Byte, // SqlDbType.TinyInt
- DbType.Binary, // SqlDbType.VarBinary
- DbType.AnsiString, // SqlDbType.VarChar
- DbType.Object, // SqlDbType.Variant
- DbType.Object, // SqlDbType.Row
- DbType.Xml, // SqlDbType.Xml
- DbType.String, // SqlDbType.NVarChar, place holder
- DbType.String, // SqlDbType.NVarChar, place holder
- DbType.String, // SqlDbType.NVarChar, place holder
- DbType.Object, // SqlDbType.Udt
- DbType.Object, // SqlDbType.Structured
- DbType.Date, // SqlDbType.Date
- DbType.Time, // SqlDbType.Time
- DbType.DateTime2, // SqlDbType.DateTime2
- DbType.DateTimeOffset // SqlDbType.DateTimeOffset
- };
-
- private void SetDefaultsForType(SqlDbType dbType)
- {
- if (SqlDbType.BigInt <= dbType && SqlDbType.DateTimeOffset >= dbType)
- {
- SqlMetaData smdDflt = sxm_rgDefaults[(int)dbType];
- m_sqlDbType = dbType;
- m_lMaxLength = smdDflt.MaxLength;
- m_bPrecision = smdDflt.Precision;
- m_bScale = smdDflt.Scale;
- m_lLocale = smdDflt.LocaleId;
- m_eCompareOptions = smdDflt.CompareOptions;
- }
- }
-
- // Array of default-valued metadata ordered by corresponding SqlDbType.
- internal static SqlMetaData[] sxm_rgDefaults =
- {
- // new SqlMetaData(name, DbType, SqlDbType, MaxLen, Prec, Scale, Locale, DatabaseName, SchemaName, isPartialLength)
- new SqlMetaData("bigint", SqlDbType.BigInt,
- 8, 19, 0, 0, SqlCompareOptions.None, false), // SqlDbType.BigInt
- new SqlMetaData("binary", SqlDbType.Binary,
- 1, 0, 0, 0, SqlCompareOptions.None, false), // SqlDbType.Binary
- new SqlMetaData("bit", SqlDbType.Bit,
- 1, 1, 0, 0, SqlCompareOptions.None, false), // SqlDbType.Bit
- new SqlMetaData("char", SqlDbType.Char,
- 1, 0, 0, 0, x_eDefaultStringCompareOptions, false), // SqlDbType.Char
- new SqlMetaData("datetime", SqlDbType.DateTime,
- 8, 23, 3, 0, SqlCompareOptions.None, false), // SqlDbType.DateTime
- new SqlMetaData("decimal", SqlDbType.Decimal,
- 9, 18, 0, 0, SqlCompareOptions.None, false), // SqlDbType.Decimal
- new SqlMetaData("float", SqlDbType.Float,
- 8, 53, 0, 0, SqlCompareOptions.None, false), // SqlDbType.Float
- new SqlMetaData("image", SqlDbType.Image,
- x_lMax, 0, 0, 0, SqlCompareOptions.None, false), // SqlDbType.Image
- new SqlMetaData("int", SqlDbType.Int,
- 4, 10, 0, 0, SqlCompareOptions.None, false), // SqlDbType.Int
- new SqlMetaData("money", SqlDbType.Money,
- 8, 19, 4, 0, SqlCompareOptions.None, false), // SqlDbType.Money
- new SqlMetaData("nchar", SqlDbType.NChar,
- 1, 0, 0, 0, x_eDefaultStringCompareOptions, false), // SqlDbType.NChar
- new SqlMetaData("ntext", SqlDbType.NText,
- x_lMax, 0, 0, 0, x_eDefaultStringCompareOptions, false), // SqlDbType.NText
- new SqlMetaData("nvarchar", SqlDbType.NVarChar,
- x_lServerMaxUnicode, 0, 0, 0, x_eDefaultStringCompareOptions, false), // SqlDbType.NVarChar
- new SqlMetaData("real", SqlDbType.Real,
- 4, 24, 0, 0, SqlCompareOptions.None, false), // SqlDbType.Real
- new SqlMetaData("uniqueidentifier", SqlDbType.UniqueIdentifier,
- 16, 0, 0, 0, SqlCompareOptions.None, false), // SqlDbType.UniqueIdentifier
- new SqlMetaData("smalldatetime", SqlDbType.SmallDateTime,
- 4, 16, 0, 0, SqlCompareOptions.None, false), // SqlDbType.SmallDateTime
- new SqlMetaData("smallint", SqlDbType.SmallInt,
- 2, 5, 0, 0, SqlCompareOptions.None, false), // SqlDbType.SmallInt
- new SqlMetaData("smallmoney", SqlDbType.SmallMoney,
- 4, 10, 4, 0, SqlCompareOptions.None, false), // SqlDbType.SmallMoney
- new SqlMetaData("text", SqlDbType.Text,
- x_lMax, 0, 0, 0, x_eDefaultStringCompareOptions, false), // SqlDbType.Text
- new SqlMetaData("timestamp", SqlDbType.Timestamp,
- 8, 0, 0, 0, SqlCompareOptions.None, false), // SqlDbType.Timestamp
- new SqlMetaData("tinyint", SqlDbType.TinyInt,
- 1, 3, 0, 0, SqlCompareOptions.None, false), // SqlDbType.TinyInt
- new SqlMetaData("varbinary", SqlDbType.VarBinary,
- x_lServerMaxBinary, 0, 0, 0, SqlCompareOptions.None, false), // SqlDbType.VarBinary
- new SqlMetaData("varchar", SqlDbType.VarChar,
- x_lServerMaxANSI, 0, 0, 0, x_eDefaultStringCompareOptions, false), // SqlDbType.VarChar
- new SqlMetaData("sql_variant", SqlDbType.Variant,
- 8016, 0, 0, 0, SqlCompareOptions.None, false), // SqlDbType.Variant
- new SqlMetaData("nvarchar", SqlDbType.NVarChar,
- 1, 0, 0, 0, x_eDefaultStringCompareOptions, false), // Placeholder for value 24
- new SqlMetaData("xml", SqlDbType.Xml,
- x_lMax, 0, 0, 0, x_eDefaultStringCompareOptions, true), // SqlDbType.Xml
- new SqlMetaData("nvarchar", SqlDbType.NVarChar,
- 1, 0, 0, 0, x_eDefaultStringCompareOptions, false), // Placeholder for value 26
- new SqlMetaData("nvarchar", SqlDbType.NVarChar,
- x_lServerMaxUnicode, 0, 0, 0, x_eDefaultStringCompareOptions, false), // Placeholder for value 27
- new SqlMetaData("nvarchar", SqlDbType.NVarChar,
- x_lServerMaxUnicode, 0, 0, 0, x_eDefaultStringCompareOptions, false), // Placeholder for value 28
- new SqlMetaData("udt", SqlDbType.Udt,
- 0, 0, 0, 0, SqlCompareOptions.None, false), // SqlDbType.Udt = 29 Bug Fix: 302698
- new SqlMetaData("table", SqlDbType.Structured,
- 0, 0, 0, 0, SqlCompareOptions.None, false), // SqlDbType.Structured
- new SqlMetaData("date", SqlDbType.Date,
- 3, 10,0, 0, SqlCompareOptions.None, false), // SqlDbType.Date
- new SqlMetaData("time", SqlDbType.Time,
- 5, 0, 7, 0, SqlCompareOptions.None, false), // SqlDbType.Time
- new SqlMetaData("datetime2", SqlDbType.DateTime2,
- 8, 0, 7, 0, SqlCompareOptions.None, false), // SqlDbType.DateTime2
- new SqlMetaData("datetimeoffset", SqlDbType.DateTimeOffset,
- 10, 0, 7, 0, SqlCompareOptions.None, false), // SqlDbType.DateTimeOffset
- };
- }
-}
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/SqlRecordBuffer.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/SqlRecordBuffer.cs
deleted file mode 100644
index 2970fb2145..0000000000
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/SqlRecordBuffer.cs
+++ /dev/null
@@ -1,615 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using System.Data;
-using System.Data.SqlTypes;
-using System.Diagnostics;
-using System.Runtime.InteropServices;
-using Microsoft.Data.Common;
-
-namespace Microsoft.Data.SqlClient.Server
-{
- internal sealed class SqlRecordBuffer
- {
-
- internal enum StorageType
- {
- Boolean,
- Byte,
- ByteArray,
- CharArray,
- DateTime,
- DateTimeOffset,
- Double,
- Guid,
- Int16,
- Int32,
- Int64,
- Single,
- String,
- SqlDecimal,
- TimeSpan,
- }
-
- [StructLayout(LayoutKind.Explicit)]
- internal struct Storage
- {
- [FieldOffset(0)] internal Boolean _boolean;
- [FieldOffset(0)] internal Byte _byte;
- [FieldOffset(0)] internal DateTime _dateTime;
- [FieldOffset(0)] internal DateTimeOffset _dateTimeOffset;
- [FieldOffset(0)] internal Double _double;
- [FieldOffset(0)] internal Guid _guid;
- [FieldOffset(0)] internal Int16 _int16;
- [FieldOffset(0)] internal Int32 _int32;
- [FieldOffset(0)] internal Int64 _int64; // also used to BytesLength and CharsLength
- [FieldOffset(0)] internal Single _single;
- [FieldOffset(0)] internal TimeSpan _timeSpan;
- }
-
- private bool _isNull;
- private StorageType _type;
- private Storage _value;
- private object _object; // String, SqlDecimal
- private SmiMetaData _metadata; // for variant
- private bool _isMetaSet; // flag to indicate whether we have set the variant metadata
-
- internal SqlRecordBuffer(SmiMetaData metaData)
- {
- _isNull = true;
- }
-
- internal bool IsNull
- {
- get
- {
- return _isNull;
- }
- }
-
- internal Boolean Boolean
- {
- get
- {
- Debug.Assert(!_isNull, "Null data type");
- Debug.Assert(StorageType.Boolean == _type, "Wrong storage type: " + _type);
-
- return _value._boolean;
- }
- set
- {
- _value._boolean = value;
- _type = StorageType.Boolean;
- _isNull = false;
- }
- }
-
- internal Byte Byte
- {
- get
- {
- Debug.Assert(!_isNull, "Null data type");
- Debug.Assert(StorageType.Byte == _type, "Wrong storage type: " + _type);
-
- return _value._byte;
- }
- set
- {
- _value._byte = value;
- _type = StorageType.Byte;
- _isNull = false;
- }
- }
-
- internal DateTime DateTime
- {
- get
- {
- Debug.Assert(!_isNull, "Null data type");
- Debug.Assert(StorageType.DateTime == _type, "Wrong storage type: " + _type);
-
- return _value._dateTime;
- }
- set
- {
- _value._dateTime = value;
- _type = StorageType.DateTime;
- _isNull = false;
- // in case of variant types, the caller first sets metadata and than the value. we need to keep metadata after first value set
- // if value is set second time without variant metadata, reset the metadata since it is not variant anymore
- if (_isMetaSet)
- {
- _isMetaSet = false;
- }
- else
- {
- _metadata = null; // need to clear the variant metadata
- }
- }
- }
-
- internal DateTimeOffset DateTimeOffset
- {
- get
- {
- Debug.Assert(!_isNull, "Null data type");
- Debug.Assert(StorageType.DateTimeOffset == _type, "Wrong storage type: " + _type);
-
- return _value._dateTimeOffset;
- }
- set
- {
- _value._dateTimeOffset = value;
- _type = StorageType.DateTimeOffset;
- _isNull = false;
- }
- }
-
- internal Double Double
- {
- get
- {
- Debug.Assert(!_isNull, "Null data type");
- Debug.Assert(StorageType.Double == _type, "Wrong storage type: " + _type);
-
- return _value._double;
- }
- set
- {
- _value._double = value;
- _type = StorageType.Double;
- _isNull = false;
- }
- }
-
- internal Guid Guid
- {
- get
- {
- Debug.Assert(!_isNull, "Null data type");
- Debug.Assert(StorageType.Guid == _type, "Wrong storage type: " + _type);
-
- return _value._guid;
- }
- set
- {
- _value._guid = value;
- _type = StorageType.Guid;
- _isNull = false;
- }
- }
-
- internal Int16 Int16
- {
- get
- {
- Debug.Assert(!_isNull, "Null data type");
- Debug.Assert(StorageType.Int16 == _type, "Wrong storage type: " + _type);
-
- return _value._int16;
- }
- set
- {
- _value._int16 = value;
- _type = StorageType.Int16;
- _isNull = false;
- }
- }
-
- internal Int32 Int32
- {
- get
- {
- Debug.Assert(!_isNull, "Null data type");
- Debug.Assert(StorageType.Int32 == _type, "Wrong storage type: " + _type);
-
- return _value._int32;
- }
- set
- {
- _value._int32 = value;
- _type = StorageType.Int32;
- _isNull = false;
- }
- }
-
- internal Int64 Int64
- {
- get
- {
- Debug.Assert(!_isNull, "Null data type");
- Debug.Assert(StorageType.Int64 == _type, "Wrong storage type: " + _type);
-
- return _value._int64;
- }
- set
- {
- _value._int64 = value;
- _type = StorageType.Int64;
- _isNull = false;
- if (_isMetaSet)
- {
- _isMetaSet = false;
- }
- else
- {
- _metadata = null; // need to clear the variant metadata
- }
- }
- }
-
- internal Single Single
- {
- get
- {
- Debug.Assert(!_isNull, "Null data type");
- Debug.Assert(StorageType.Single == _type, "Wrong storage type: " + _type);
-
- return _value._single;
- }
- set
- {
- _value._single = value;
- _type = StorageType.Single;
- _isNull = false;
- }
- }
-
- internal String String
- {
- get
- {
- Debug.Assert(!_isNull, "Null data type");
-
- if (StorageType.String == _type)
- {
- return (String)_object;
- }
- else if (StorageType.CharArray == _type)
- {
- return new String((char[])_object, 0, (int)CharsLength);
- }
- else
- {
- // Xml may be stored as byte array, yet have GetString called against it.
- Debug.Assert(StorageType.ByteArray == _type, "Wrong storage type: " + _type);
- System.IO.Stream byteStream = new System.IO.MemoryStream((byte[])_object, false);
- return (new SqlXml(byteStream)).Value;
- }
- }
- set
- {
- Debug.Assert(null != value, "");
-
- _object = value;
- _value._int64 = ((string)value).Length;
- _type = StorageType.String;
- _isNull = false;
- if (_isMetaSet)
- {
- _isMetaSet = false;
- }
- else
- {
- _metadata = null; // need to clear the variant metadata
- }
- }
- }
-
- internal SqlDecimal SqlDecimal
- {
- get
- {
- Debug.Assert(!_isNull, "Null data type");
- Debug.Assert(StorageType.SqlDecimal == _type, "Wrong storage type: " + _type);
-
- return (SqlDecimal)_object;
- }
- set
- {
- Debug.Assert(!value.IsNull, "Null input");
-
- _object = value;
- _type = StorageType.SqlDecimal;
- _isNull = false;
- }
- }
-
- internal TimeSpan TimeSpan
- {
- get
- {
- Debug.Assert(!_isNull, "Null data type");
- Debug.Assert(StorageType.TimeSpan == _type, "Wrong storage type: " + _type);
-
- return _value._timeSpan;
- }
- set
- {
- _value._timeSpan = value;
- _type = StorageType.TimeSpan;
- _isNull = false;
- }
- }
-
- internal Int64 BytesLength
- {
- get
- {
- Debug.Assert(!_isNull, "Null data type");
-
- // sometimes Xml is stored as string, but must support byte access
- if (StorageType.String == _type)
- {
- ConvertXmlStringToByteArray();
- }
- else
- {
- Debug.Assert(StorageType.ByteArray == _type, "Wrong storage type: " + _type);
- }
-
- return _value._int64;
- }
- set
- {
- if (0 == value)
- {
- _value._int64 = value;
- _object = new byte[0];
- _type = StorageType.ByteArray;
- _isNull = false;
- }
- else
- {
- Debug.Assert(!_isNull, "Null data type");
- Debug.Assert(StorageType.ByteArray == _type, "Wrong storage type: " + _type);
- Debug.Assert(value > 0 && value <= ((byte[])_object).Length, "Invalid BytesLength");
-
- _value._int64 = value;
- }
- }
- }
-
- internal Int64 CharsLength
- {
- get
- {
- Debug.Assert(!_isNull, "Null data type");
- Debug.Assert(StorageType.CharArray == _type || StorageType.String == _type, "Wrong storage type: " + _type);
-
- return _value._int64;
- }
- set
- {
- if (0 == value)
- {
- _value._int64 = value;
- _object = new char[0];
- _type = StorageType.CharArray;
- _isNull = false;
- }
- else
- {
- Debug.Assert(!_isNull, "Null data type");
- Debug.Assert(StorageType.CharArray == _type || StorageType.String == _type, "Wrong storage type: " + _type);
- Debug.Assert(value > 0 &&
- ((StorageType.CharArray == _type && value <= ((char[])_object).Length) || (StorageType.String == _type && value <= ((string)_object).Length)),
- "Invalid CharsLength");
-
- _value._int64 = value;
- }
- }
- }
-
- internal SmiMetaData VariantType
- {
- get
- {
- Debug.Assert(!_isNull, "Null data type");
- Debug.Assert(_metadata == null
- || _metadata.SqlDbType == SqlDbType.Money
- || _metadata.SqlDbType == SqlDbType.NVarChar
- || _metadata.SqlDbType == SqlDbType.DateTime
- || _metadata.SqlDbType == SqlDbType.Date
- || _metadata.SqlDbType == SqlDbType.DateTime2,
- "Invalid metadata");
-
- switch (_type)
- {
- case StorageType.Boolean:
- return SmiMetaData.DefaultBit;
- case StorageType.Byte:
- return SmiMetaData.DefaultTinyInt;
- case StorageType.ByteArray:
- return SmiMetaData.DefaultVarBinary;
- case StorageType.CharArray:
- return SmiMetaData.DefaultNVarChar;
- case StorageType.DateTime:
- return _metadata ?? SmiMetaData.DefaultDateTime;
- case StorageType.DateTimeOffset:
- return SmiMetaData.DefaultDateTimeOffset;
- case StorageType.Double:
- return SmiMetaData.DefaultFloat;
- case StorageType.Guid:
- return SmiMetaData.DefaultUniqueIdentifier;
- case StorageType.Int16:
- return SmiMetaData.DefaultSmallInt;
- case StorageType.Int32:
- return SmiMetaData.DefaultInt;
- case StorageType.Int64:
- return _metadata ?? SmiMetaData.DefaultBigInt;
- case StorageType.Single:
- return SmiMetaData.DefaultReal;
- case StorageType.String:
- return _metadata ?? SmiMetaData.DefaultNVarChar;
- case StorageType.SqlDecimal:
- return new SmiMetaData(SqlDbType.Decimal, 17, ((SqlDecimal)_object).Precision, ((SqlDecimal)_object).Scale, 0, SqlCompareOptions.None, null);
- case StorageType.TimeSpan:
- return SmiMetaData.DefaultTime;
- }
- return null;
- }
- set
- {
- Debug.Assert(value != null && (value.SqlDbType == SqlDbType.Money || value.SqlDbType == SqlDbType.NVarChar),
- "Invalid metadata");
-
- _metadata = value;
- _isMetaSet = true;
- }
- }
-
- internal int GetBytes(long fieldOffset, byte[] buffer, int bufferOffset, int length)
- {
- int ndataIndex = (int)fieldOffset;
-
- Debug.Assert(!_isNull, "Null data type");
- // sometimes Xml is stored as string, but must support byte access
- if (StorageType.String == _type)
- {
- ConvertXmlStringToByteArray();
- }
- else
- {
- Debug.Assert(StorageType.ByteArray == _type, "Wrong storage type: " + _type);
- }
- Debug.Assert(null != buffer, "Null buffer");
- Debug.Assert(ndataIndex + length <= BytesLength, "Invalid fieldOffset or length");
-
- Buffer.BlockCopy((byte[])_object, ndataIndex, buffer, bufferOffset, length);
-
- return length;
- }
-
- internal int GetChars(long fieldOffset, char[] buffer, int bufferOffset, int length)
- {
- int ndataIndex = (int)fieldOffset;
-
- Debug.Assert(!_isNull, "Null data type");
- Debug.Assert(StorageType.CharArray == _type || StorageType.String == _type, "Wrong storage type: " + _type);
- Debug.Assert(null != buffer, "Null buffer");
- Debug.Assert(ndataIndex + length <= CharsLength, "Invalid fieldOffset or length");
-
- if (StorageType.CharArray == _type)
- {
- Array.Copy((char[])_object, ndataIndex, buffer, bufferOffset, length);
- }
- else
- { // String type
- ((string)_object).CopyTo(ndataIndex, buffer, bufferOffset, length);
- }
-
- return length;
- }
-
- internal int SetBytes(long fieldOffset, byte[] buffer, int bufferOffset, int length)
- {
- int ndataIndex = (int)fieldOffset;
-
- if (IsNull || StorageType.ByteArray != _type)
- {
- if (ndataIndex != 0)
- { // set the first time: should start from the beginning
- throw ADP.ArgumentOutOfRange("fieldOffset");
- }
- _object = new byte[length];
- _type = StorageType.ByteArray;
- _isNull = false;
- BytesLength = length;
- }
- else
- {
- if (ndataIndex > BytesLength)
- { // no gap is allowed
- throw ADP.ArgumentOutOfRange("fieldOffset");
- }
- if (ndataIndex + length > BytesLength)
- { // beyond the current length
- int cbytes = ((byte[])_object).Length;
-
- if (ndataIndex + length > cbytes)
- { // dynamic expansion
- byte[] data = new byte[Math.Max(ndataIndex + length, 2 * cbytes)];
- Buffer.BlockCopy((byte[])_object, 0, data, 0, (int)BytesLength);
- _object = data;
-
- }
- BytesLength = ndataIndex + length;
- }
- }
-
- Buffer.BlockCopy(buffer, bufferOffset, (byte[])_object, ndataIndex, length);
-
- return length;
- }
-
- internal int SetChars(long fieldOffset, char[] buffer, int bufferOffset, int length)
- {
- int ndataIndex = (int)fieldOffset;
-
- if (IsNull || (StorageType.CharArray != _type && StorageType.String != _type))
- {
- if (ndataIndex != 0)
- { // set the first time: should start from the beginning
- throw ADP.ArgumentOutOfRange("fieldOffset");
- }
- _object = new char[length];
- _type = StorageType.CharArray;
- _isNull = false;
- CharsLength = length;
- }
- else
- {
- if (ndataIndex > CharsLength)
- { // no gap is allowed
- throw ADP.ArgumentOutOfRange("fieldOffset");
- }
- if (StorageType.String == _type)
- { // convert string to char[]
- _object = ((string)_object).ToCharArray();
- _type = StorageType.CharArray;
- }
- if (ndataIndex + length > CharsLength)
- { // beyond the current length
- int cchars = ((char[])_object).Length;
-
- if (ndataIndex + length > cchars)
- { // dynamic expansion
- char[] data = new char[Math.Max(ndataIndex + length, 2 * cchars)];
- Array.Copy((char[])_object, 0, data, 0, CharsLength);
- _object = data;
- }
- CharsLength = ndataIndex + length;
- }
- }
-
- Array.Copy(buffer, bufferOffset, (char[])_object, ndataIndex, length);
-
- return length;
- }
-
- internal void SetNull()
- {
- _isNull = true;
- }
-
- // Handle case for Xml where SetString() was called, followed by GetBytes()
- private void ConvertXmlStringToByteArray()
- {
- Debug.Assert(StorageType.String == _type, "ConvertXmlStringToByteArray: Invalid storage type for conversion: " + _type.ToString());
-
- // Grab the unicode bytes, but prepend the XML unicode BOM
- string value = (string)_object;
- byte[] bytes = new byte[2 + System.Text.Encoding.Unicode.GetByteCount(value)];
- bytes[0] = 0xff;
- bytes[1] = 0xfe;
- System.Text.Encoding.Unicode.GetBytes(value, 0, value.Length, bytes, 2);
-
- _object = bytes;
- _value._int64 = bytes.Length;
- _type = StorageType.ByteArray;
- }
- }
-}
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/SqlUserDefinedAggregateAttribute.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/SqlUserDefinedAggregateAttribute.cs
deleted file mode 100644
index c5730bbb35..0000000000
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/SqlUserDefinedAggregateAttribute.cs
+++ /dev/null
@@ -1,140 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using Microsoft.Data.Common;
-
-namespace Microsoft.Data.SqlClient.Server
-{
- ///
- [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)]
- public sealed class SqlUserDefinedAggregateAttribute : Attribute
- {
- private int m_MaxByteSize;
- private bool m_fInvariantToDup;
- private bool m_fInvariantToNulls;
- private bool m_fInvariantToOrder = true;
- private bool m_fNullIfEmpty;
- private Format m_format;
- private string m_fName;
-
- ///
- // The maximum value for the maxbytesize field, in bytes.
- public const int MaxByteSizeValue = 8000;
-
- ///
- // A required attribute on all udaggs, used to indicate that the
- // given type is a udagg, and its storage format.
- public SqlUserDefinedAggregateAttribute(Format format)
- {
- switch (format)
- {
- case Format.Unknown:
- throw ADP.NotSupportedUserDefinedTypeSerializationFormat((Microsoft.Data.SqlClient.Server.Format)format, "format");
- case Format.Native:
- case Format.UserDefined:
- this.m_format = format;
- break;
- default:
- throw ADP.InvalidUserDefinedTypeSerializationFormat((Microsoft.Data.SqlClient.Server.Format)format);
- }
- }
-
- ///
- // The maximum size of this instance, in bytes. Does not have to be
- // specified for Native format serialization. The maximum value
- // for this property is specified by MaxByteSizeValue.
- public int MaxByteSize
- {
- get
- {
- return this.m_MaxByteSize;
- }
- set
- {
- // MaxByteSize of -1 means 2GB and is valid, as well as 0 to MaxByteSizeValue
- if (value < -1 || value > MaxByteSizeValue)
- {
- throw ADP.ArgumentOutOfRange(StringsHelper.GetString(Strings.SQLUDT_MaxByteSizeValue), "MaxByteSize", value);
- }
- this.m_MaxByteSize = value;
- }
- }
-
- ///
- public bool IsInvariantToDuplicates
- {
- get
- {
- return this.m_fInvariantToDup;
- }
- set
- {
- this.m_fInvariantToDup = value;
- }
- }
-
- ///
- public bool IsInvariantToNulls
- {
- get
- {
- return this.m_fInvariantToNulls;
- }
- set
- {
- this.m_fInvariantToNulls = value;
- }
- }
-
- ///
- public bool IsInvariantToOrder
- {
- get
- {
- return this.m_fInvariantToOrder;
- }
- set
- {
- this.m_fInvariantToOrder = value;
- }
- }
-
- ///
- public bool IsNullIfEmpty
- {
- get
- {
- return this.m_fNullIfEmpty;
- }
- set
- {
- this.m_fNullIfEmpty = value;
- }
- }
-
- ///
- // The on-disk format for this type.
- public Format Format
- {
- get
- {
- return this.m_format;
- }
- }
-
- ///
- public string Name
- {
- get
- {
- return m_fName;
- }
- set
- {
- m_fName = value;
- }
- }
- }
-}
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/ValueUtilsSmi.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/ValueUtilsSmi.cs
index 42a59bb154..28bc1ae376 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/ValueUtilsSmi.cs
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/ValueUtilsSmi.cs
@@ -25,13 +25,13 @@ namespace Microsoft.Data.SqlClient.Server
// as an ExtendedClrTypeCode enum for rapid access (lookup in static array is best, if possible).
internal static class ValueUtilsSmi
{
- const int __maxByteChunkSize = TdsEnums.MAXSIZE;
- const int __maxCharChunkSize = TdsEnums.MAXSIZE / sizeof(char);
- const int NoLengthLimit = (int)SmiMetaData.UnlimitedMaxLengthIndicator; // make sure we use the same constant
+ private const int __maxByteChunkSize = TdsEnums.MAXSIZE;
+ private const int __maxCharChunkSize = TdsEnums.MAXSIZE / sizeof(char);
+ private const int NoLengthLimit = (int)SmiMetaData.UnlimitedMaxLengthIndicator; // make sure we use the same constant
// Constants
- const int constBinBufferSize = 4096; // Size of the buffer used to read input parameter of type Stream
- const int constTextBufferSize = 4096; // Size of the buffer (in chars) user to read input parameter of type TextReader
+ private const int constBinBufferSize = 4096; // Size of the buffer used to read input parameter of type Stream
+ private const int constTextBufferSize = 4096; // Size of the buffer (in chars) user to read input parameter of type TextReader
//
// User-visible semantics-laden Getter/Setter support methods
@@ -65,7 +65,7 @@ internal static bool GetBoolean(SmiEventSink_Default sink, ITypedGettersV3 gette
{
throw ADP.InvalidCast();
}
- return (Boolean)result;
+ return (bool)result;
}
internal static byte GetByte(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData)
@@ -80,7 +80,7 @@ internal static byte GetByte(SmiEventSink_Default sink, ITypedGettersV3 getters,
{
throw ADP.InvalidCast();
}
- return (Byte)result;
+ return (byte)result;
}
private static long GetBytesConversion(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, long fieldOffset, byte[] buffer, int bufferOffset, int length, bool throwOnNull)
@@ -197,7 +197,7 @@ internal static long GetChars(SmiEventSink_Default sink, ITypedGettersV3 getters
return length;
}
- String value = ((String)GetValue(sink, getters, ordinal, metaData, null));
+ string value = ((string)GetValue(sink, getters, ordinal, metaData, null));
if (null == value)
{
throw ADP.InvalidCast();
@@ -254,7 +254,7 @@ internal static DateTimeOffset GetDateTimeOffset(SmiEventSink_Default sink, SmiT
return (DateTimeOffset)GetValue200(sink, getters, ordinal, metaData, null);
}
- internal static Decimal GetDecimal(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData)
+ internal static decimal GetDecimal(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData)
{
ThrowIfITypedGettersIsNull(sink, getters, ordinal);
if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.Decimal))
@@ -266,10 +266,10 @@ internal static Decimal GetDecimal(SmiEventSink_Default sink, ITypedGettersV3 ge
{
throw ADP.InvalidCast();
}
- return (Decimal)result;
+ return (decimal)result;
}
- internal static Double GetDouble(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData)
+ internal static double GetDouble(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData)
{
ThrowIfITypedGettersIsNull(sink, getters, ordinal);
if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.Double))
@@ -281,7 +281,7 @@ internal static Double GetDouble(SmiEventSink_Default sink, ITypedGettersV3 gett
{
throw ADP.InvalidCast();
}
- return (Double)result;
+ return (double)result;
}
internal static Guid GetGuid(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData)
@@ -299,7 +299,7 @@ internal static Guid GetGuid(SmiEventSink_Default sink, ITypedGettersV3 getters,
return (Guid)result;
}
- internal static Int16 GetInt16(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData)
+ internal static short GetInt16(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData)
{
ThrowIfITypedGettersIsNull(sink, getters, ordinal);
if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.Int16))
@@ -311,10 +311,10 @@ internal static Int16 GetInt16(SmiEventSink_Default sink, ITypedGettersV3 getter
{
throw ADP.InvalidCast();
}
- return (Int16)obj;
+ return (short)obj;
}
- internal static Int32 GetInt32(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData)
+ internal static int GetInt32(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData)
{
ThrowIfITypedGettersIsNull(sink, getters, ordinal);
if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.Int32))
@@ -326,10 +326,10 @@ internal static Int32 GetInt32(SmiEventSink_Default sink, ITypedGettersV3 getter
{
throw ADP.InvalidCast();
}
- return (Int32)result;
+ return (int)result;
}
- internal static Int64 GetInt64(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData)
+ internal static long GetInt64(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData)
{
ThrowIfITypedGettersIsNull(sink, getters, ordinal);
if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.Int64))
@@ -341,10 +341,10 @@ internal static Int64 GetInt64(SmiEventSink_Default sink, ITypedGettersV3 getter
{
throw ADP.InvalidCast();
}
- return (Int64)result;
+ return (long)result;
}
- internal static Single GetSingle(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData)
+ internal static float GetSingle(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData)
{
ThrowIfITypedGettersIsNull(sink, getters, ordinal);
if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.Single))
@@ -356,7 +356,7 @@ internal static Single GetSingle(SmiEventSink_Default sink, ITypedGettersV3 gett
{
throw ADP.InvalidCast();
}
- return (Single)result;
+ return (float)result;
}
internal static SqlBinary GetSqlBinary(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData)
@@ -594,7 +594,7 @@ internal static SqlDouble GetSqlDouble(SmiEventSink_Default sink, ITypedGettersV
}
else
{
- Double temp = GetDouble_Unchecked(sink, getters, ordinal);
+ double temp = GetDouble_Unchecked(sink, getters, ordinal);
result = new SqlDouble(temp);
}
}
@@ -650,7 +650,7 @@ internal static SqlInt16 GetSqlInt16(SmiEventSink_Default sink, ITypedGettersV3
}
else
{
- Int16 temp = GetInt16_Unchecked(sink, getters, ordinal);
+ short temp = GetInt16_Unchecked(sink, getters, ordinal);
result = new SqlInt16(temp);
}
}
@@ -678,7 +678,7 @@ internal static SqlInt32 GetSqlInt32(SmiEventSink_Default sink, ITypedGettersV3
}
else
{
- Int32 temp = GetInt32_Unchecked(sink, getters, ordinal);
+ int temp = GetInt32_Unchecked(sink, getters, ordinal);
result = new SqlInt32(temp);
}
}
@@ -705,7 +705,7 @@ internal static SqlInt64 GetSqlInt64(SmiEventSink_Default sink, ITypedGettersV3
}
else
{
- Int64 temp = GetInt64_Unchecked(sink, getters, ordinal);
+ long temp = GetInt64_Unchecked(sink, getters, ordinal);
result = new SqlInt64(temp);
}
}
@@ -760,7 +760,7 @@ internal static SqlSingle GetSqlSingle(SmiEventSink_Default sink, ITypedGettersV
}
else
{
- Single temp = GetSingle_Unchecked(sink, getters, ordinal);
+ float temp = GetSingle_Unchecked(sink, getters, ordinal);
result = new SqlSingle(temp);
}
}
@@ -788,7 +788,7 @@ internal static SqlString GetSqlString(SmiEventSink_Default sink, ITypedGettersV
}
else
{
- String temp = GetString_Unchecked(sink, getters, ordinal);
+ string temp = GetString_Unchecked(sink, getters, ordinal);
result = new SqlString(temp);
}
}
@@ -845,7 +845,7 @@ internal static SqlXml GetSqlXml(SmiEventSink_Default sink, ITypedGettersV3 gett
return result;
}
- internal static String GetString(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData)
+ internal static string GetString(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData)
{
ThrowIfITypedGettersIsNull(sink, getters, ordinal);
if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.String))
@@ -857,7 +857,7 @@ internal static String GetString(SmiEventSink_Default sink, ITypedGettersV3 gett
{
throw ADP.InvalidCast();
}
- return (String)obj;
+ return (string)obj;
}
internal static SqlSequentialStreamSmi GetSequentialStream(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, bool bypassTypeCheck = false)
@@ -1146,7 +1146,7 @@ SmiContext context
}
else
{
- result = __typeSpecificNullForSqlValue[(int)metaData.SqlDbType];
+ result = s_typeSpecificNullForSqlValue[(int)metaData.SqlDbType];
}
}
else
@@ -1196,7 +1196,7 @@ SmiContext context
}
else
{
- result = __typeSpecificNullForSqlValue[(int)metaData.SqlDbType];
+ result = s_typeSpecificNullForSqlValue[(int)metaData.SqlDbType];
}
}
else
@@ -1291,7 +1291,7 @@ SmiContext context
}
// null return values for SqlClient 1.1-compatible GetSqlValue()
- private static object[] __typeSpecificNullForSqlValue = {
+ private static object[] s_typeSpecificNullForSqlValue = {
SqlInt64.Null, // SqlDbType.BigInt
SqlBinary.Null, // SqlDbType.Binary
SqlBoolean.Null, // SqlDbType.Bit
@@ -1559,19 +1559,19 @@ SqlBuffer targetBuffer // destination
// Strongly-typed setters are a bit simpler than their corresponding getters.
// 1) check to make sure the type is compatible (exception if not)
// 2) push the data
- internal static void SetDBNull(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, Boolean value)
+ internal static void SetDBNull(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, bool value)
{
SetDBNull_Unchecked(sink, setters, ordinal);
}
- internal static void SetBoolean(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, Boolean value)
+ internal static void SetBoolean(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, bool value)
{
ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.Boolean);
SetBoolean_Unchecked(sink, setters, ordinal, value);
}
- internal static void SetByte(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, Byte value)
+ internal static void SetByte(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, byte value)
{
ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.Byte);
@@ -1583,7 +1583,7 @@ internal static long SetBytes(SmiEventSink_Default sink, ITypedSettersV3 setters
ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.ByteArray);
if (null == buffer)
{
- throw ADP.ArgumentNull("buffer");
+ throw ADP.ArgumentNull(nameof(buffer));
}
length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, fieldOffset, buffer.Length, bufferOffset, length);
Debug.Assert(length >= 0, "Buffer.Length was invalid!");
@@ -1624,7 +1624,7 @@ internal static long SetChars(SmiEventSink_Default sink, ITypedSettersV3 setters
ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.CharArray);
if (null == buffer)
{
- throw ADP.ArgumentNull("buffer");
+ throw ADP.ArgumentNull(nameof(buffer));
}
length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, fieldOffset, buffer.Length, bufferOffset, length);
Debug.Assert(length >= 0, "Buffer.Length was invalid!");
@@ -1657,14 +1657,14 @@ internal static void SetDateTimeOffset(SmiEventSink_Default sink, ITypedSettersV
SetDateTimeOffset_Unchecked(sink, (SmiTypedGetterSetter)setters, ordinal, value);
}
- internal static void SetDecimal(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, Decimal value)
+ internal static void SetDecimal(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, decimal value)
{
ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.Decimal);
SetDecimal_PossiblyMoney(sink, setters, ordinal, metaData, value);
}
- internal static void SetDouble(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, Double value)
+ internal static void SetDouble(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, double value)
{
ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.Double);
@@ -1678,28 +1678,28 @@ internal static void SetGuid(SmiEventSink_Default sink, ITypedSettersV3 setters,
SetGuid_Unchecked(sink, setters, ordinal, value);
}
- internal static void SetInt16(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, Int16 value)
+ internal static void SetInt16(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, short value)
{
ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.Int16);
SetInt16_Unchecked(sink, setters, ordinal, value);
}
- internal static void SetInt32(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, Int32 value)
+ internal static void SetInt32(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, int value)
{
ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.Int32);
SetInt32_Unchecked(sink, setters, ordinal, value);
}
- internal static void SetInt64(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, Int64 value)
+ internal static void SetInt64(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, long value)
{
ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.Int64);
SetInt64_Unchecked(sink, setters, ordinal, value);
}
- internal static void SetSingle(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, Single value)
+ internal static void SetSingle(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, float value)
{
ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.Single);
@@ -1815,7 +1815,7 @@ internal static void SetSqlXml(SmiEventSink_Default sink, ITypedSettersV3 setter
SetSqlXml_Unchecked(sink, setters, ordinal, value);
}
- internal static void SetString(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, String value)
+ internal static void SetString(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, string value)
{
ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.String);
@@ -1861,10 +1861,10 @@ int offset
case ExtendedClrTypeCode.Invalid:
throw ADP.UnknownDataType(value.GetType());
case ExtendedClrTypeCode.Boolean:
- SetBoolean_Unchecked(sink, setters, ordinal, (Boolean)value);
+ SetBoolean_Unchecked(sink, setters, ordinal, (bool)value);
break;
case ExtendedClrTypeCode.Byte:
- SetByte_Unchecked(sink, setters, ordinal, (Byte)value);
+ SetByte_Unchecked(sink, setters, ordinal, (byte)value);
break;
case ExtendedClrTypeCode.Char:
{
@@ -1880,27 +1880,27 @@ int offset
SetDBNull_Unchecked(sink, setters, ordinal);
break;
case ExtendedClrTypeCode.Decimal:
- SetDecimal_PossiblyMoney(sink, setters, ordinal, metaData, (Decimal)value);
+ SetDecimal_PossiblyMoney(sink, setters, ordinal, metaData, (decimal)value);
break;
case ExtendedClrTypeCode.Double:
- SetDouble_Unchecked(sink, setters, ordinal, (Double)value);
+ SetDouble_Unchecked(sink, setters, ordinal, (double)value);
break;
case ExtendedClrTypeCode.Empty:
SetDBNull_Unchecked(sink, setters, ordinal);
break;
case ExtendedClrTypeCode.Int16:
- SetInt16_Unchecked(sink, setters, ordinal, (Int16)value);
+ SetInt16_Unchecked(sink, setters, ordinal, (short)value);
break;
case ExtendedClrTypeCode.Int32:
- SetInt32_Unchecked(sink, setters, ordinal, (Int32)value);
+ SetInt32_Unchecked(sink, setters, ordinal, (int)value);
break;
case ExtendedClrTypeCode.Int64:
- SetInt64_Unchecked(sink, setters, ordinal, (Int64)value);
+ SetInt64_Unchecked(sink, setters, ordinal, (long)value);
break;
case ExtendedClrTypeCode.SByte:
throw ADP.InvalidCast();
case ExtendedClrTypeCode.Single:
- SetSingle_Unchecked(sink, setters, ordinal, (Single)value);
+ SetSingle_Unchecked(sink, setters, ordinal, (float)value);
break;
case ExtendedClrTypeCode.String:
SetString_LengthChecked(sink, setters, ordinal, metaData, (string)value, offset);
@@ -1981,7 +1981,7 @@ int offset
SetXmlReader_Unchecked(sink, setters, ordinal, ((XmlDataFeed)value)._source);
break;
default:
- Debug.Assert(false, "Unvalidated extendedtypecode: " + typeCode);
+ Debug.Fail("Unvalidated extendedtypecode: " + typeCode);
break;
}
}
@@ -2185,11 +2185,9 @@ internal static void FillCompatibleITypedSettersFromReader(SmiEventSink_Default
// In order for us to get here we would have to have an
// invalid instance of SqlDbType, or one would have to add
// new member to SqlDbType without adding a case in this
- // switch, hence the assert - it must be bug in our code
- // not invalid user parameters.
- Debug.Assert(false, "unsupported DbType:" + metaData[i].SqlDbType.ToString());
+ // switch, hence the assert.
+ Debug.Fail("unsupported DbType:" + metaData[i].SqlDbType.ToString());
throw ADP.NotSupported();
-
}
}
}
@@ -2399,11 +2397,9 @@ internal static void FillCompatibleSettersFromReader(SmiEventSink_Default sink,
// In order for us to get here we would have to have an
// invalid instance of SqlDbType, or one would have to add
// new member to SqlDbType without adding a case in this
- // switch, hence the assert - it must be bug in our code
- // not invalid user parameters.
+ // switch, hence the assert.
Debug.Fail("unsupported DbType:" + metaData[i].SqlDbType.ToString());
throw ADP.NotSupported();
-
}
}
}
@@ -2776,7 +2772,7 @@ private static object GetUdt_LengthChecked(SmiEventSink_Default sink, ITypedGett
{
Type t = metaData.Type;
Debug.Assert(t != null, "Unexpected null of udtType on GetUdt_LengthChecked!");
- result = t.InvokeMember("Null", BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.Static, null, null, new Object[] { }, CultureInfo.InvariantCulture);
+ result = t.InvokeMember("Null", BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.Static, null, null, Array.Empty
+
+
+
+ true
+ ContinuousIntegrationBuild=$(BuildForRelease);EmbedUntrackedSources=$(BuildForRelease)
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index b43e2df35a..3a30ccbc5f 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -23,12 +23,11 @@
-->
Project$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb
- true$([System.IO.Path]::Combine('$(IntermediateOutputPath)','$(TargetFrameworkMoniker).AssemblyAttributes$(DefaultLanguageSourceExtension)'))
-
+
diff --git a/src/Microsoft.Data.SqlClient/add-ons/Directory.Build.props b/src/Microsoft.Data.SqlClient/add-ons/Directory.Build.props
index a70373e4cf..1214fc9139 100644
--- a/src/Microsoft.Data.SqlClient/add-ons/Directory.Build.props
+++ b/src/Microsoft.Data.SqlClient/add-ons/Directory.Build.props
@@ -7,7 +7,6 @@
Project$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb
- truetrue
From 661b640d3629f4ae87c186222f944c57562f1584 Mon Sep 17 00:00:00 2001
From: Cheena Malhotra
Date: Wed, 6 Jan 2021 11:38:09 -0800
Subject: [PATCH 018/509] Version change and minor edits (#866)
---
BUILDGUIDE.md | 2 +-
buildAddons.cmd | 1 +
contributing-workflow.md | 38 +++++++++++++++++++++++++++++++++-----
roadmap.md | 4 ++--
tools/props/Versions.props | 2 +-
5 files changed, 38 insertions(+), 9 deletions(-)
diff --git a/BUILDGUIDE.md b/BUILDGUIDE.md
index 41ff39445d..b9879fb64c 100644
--- a/BUILDGUIDE.md
+++ b/BUILDGUIDE.md
@@ -25,7 +25,7 @@ Once the environment is setup properly, execute the desired set of commands belo
```
```bash
-> msbuild /p:Platform=x86
+> msbuild /p:Platform=Win32
# Builds the .NET Framework (NetFx) driver for Win32 (x86) platform on Windows.
```
diff --git a/buildAddons.cmd b/buildAddons.cmd
index e958ed14cb..3a6f5a0f78 100644
--- a/buildAddons.cmd
+++ b/buildAddons.cmd
@@ -2,6 +2,7 @@ call :pauseOnError msbuild /p:configuration=Release /t:clean
call :pauseOnError msbuild /p:configuration=Release /t:BuildAllConfigurations
call :pauseOnError msbuild /p:configuration=Release /t:BuildAKVNetFx
call :pauseOnError msbuild /p:configuration=Release /t:BuildAKVNetCoreAllOS
+call :pauseOnError msbuild /p:configuration=Release /t:BuildAKVNetStAllOS
call :pauseOnError msbuild /p:configuration=Release /t:GenerateAKVProviderNugetPackage
goto :eof
diff --git a/contributing-workflow.md b/contributing-workflow.md
index 374e843ae1..52ee5e5e15 100644
--- a/contributing-workflow.md
+++ b/contributing-workflow.md
@@ -6,7 +6,7 @@ You can contribute to Microsoft.Data.SqlClient with issues and PRs. Simply filin
We use and recommend the following workflow:
-1. Create an issue for your work.
+1. Create an issue for your work.
- You can skip this step for trivial changes.
- Reuse an existing issue on the topic, if there is one.
- Get agreement from the team and the community that your proposed change is a good one.
@@ -15,8 +15,8 @@ We use and recommend the following workflow:
- For any other improvements in the driver, add a Label "**Enhancement**" to your issue.
- Clearly state that you are going to take on implementing it, if that's the case. You can request that the issue be assigned to you. Note: The issue filer and the implementer don't have to be the same person.
2. Create a personal fork of the repository on GitHub (if you don't already have one).
-3. Create a branch off of master (`git checkout -b mybranch`).
- - Name the branch so that it clearly communicates your intentions, such as issue-123 or githubhandle-issue.
+3. Create a branch off of master (`git checkout -b mybranch`).
+ - Name the branch so that it clearly communicates your intentions, such as issue-123 or githubhandle-issue.
- Branches are useful since they isolate your changes from incoming changes from upstream. They also enable you to create multiple PRs from the same fork.
4. Make and commit your changes.
- Please follow our [Commit Messages](contributing.md#commit-messages) guidance.
@@ -41,7 +41,7 @@ If the CI build fails for any reason, the PR issue will be updated with a link t
## PR Feedback
-Microsoft team and community members will provide feedback on your change. Community feedback is highly valued. You will often see the absence of team feedback if the community has already provided good review feedback.
+Microsoft team and community members will provide feedback on your change. Community feedback is highly valued. You will often see the absence of team feedback if the community has already provided good review feedback.
1 or more Microsoft team members will review every PR prior to merge. They will often reply with "LGTM, modulo comments". That means that the PR will be merged once the feedback is resolved. "LGTM" == "looks good to me".
@@ -61,6 +61,16 @@ For testing PR changes and ensure they work fine, we maintain a public feed that
**Add this feed to NuGet Sources**
+```xml
+
+
+
+
+
+
+
+```
+OR
```cmd
nuget.exe sources Add -Name "Microsoft.Data.SqlClient.Commits" -Source "https://pkgs.dev.azure.com/sqlclientdrivers-ci/sqlclient/_packaging/Microsoft.Data.SqlClient.Commits/nuget/v3/index.json"
```
@@ -80,8 +90,26 @@ The package naming conventions follow SemVer 2.0.0 and also provide changeset in
Package names will be like: `Microsoft.Data.SqlClient.1.1.0-build.19250.1-c21aa7c.nupkg`
Breaking down:
-- `1.1.0-build` - Identitier for currently active driver version in Build.
+- `1.1.0-build` - Identifier for currently active driver version in Build.
- `19250.1` - Unique identifier to keep latest PRs on top of the feed.
- `c21aa7c` - Short Commit Id to identify merged commit in `master`.
> Note: This public feed is only for testing and validating new PR changes. Packages from feed will be eventually removed when the maximum NuGet Package limit of **50** is reached. We do not recommend using packages from this feed in client applications.
+
+## Nightly builds
+
+We also maintain NuGet feed for Nightly builds that are generated when new changes are merged in the repository. To access Nightly builds, add below configuration to package sources:
+
+```xml
+
+
+
+
+
+
+
+```
+OR
+```cmd
+nuget.exe sources Add -Name "Microsoft.Data.SqlClient.dev" -Source "https://pkgs.dev.azure.com/sqlclientdrivers-ci/sqlclient/_packaging/Microsoft.Data.SqlClient.dev/nuget/v3/index.json"
+```
diff --git a/roadmap.md b/roadmap.md
index a9c8f5308d..e1c2b8a78c 100644
--- a/roadmap.md
+++ b/roadmap.md
@@ -11,10 +11,10 @@ The Microsoft.Data.SqlClient roadmap communicates project priorities for evolvin
| Milestone | Release Date | Project Board |
|---------------------------|--------------|---------------|
-| Microsoft.Data.SqlClient v1.0 (servicing) | As needed (see also [1.0 releases](https://github.com/dotnet/sqlclient/blob/master/release-notes/1.0)) | Closed |
| Microsoft.Data.SqlClient v1.1 (servicing) | As needed (see also [1.1 releases](https://github.com/dotnet/sqlclient/blob/master/release-notes/1.1)) | Closed |
| Microsoft.Data.SqlClient v2.0 (servicing) | As needed (see also [2.0 releases](https://github.com/dotnet/sqlclient/blob/master/release-notes/2.0)) | Closed |
-| Microsoft.Data.SqlClient v2.1 | GA (General Availability) estimated for November 2020 | [SqlClient 2.1.0](https://github.com/dotnet/SqlClient/projects/6) |
+| Microsoft.Data.SqlClient v2.1 (servicing) | As needed (see also [2.1 releases](https://github.com/dotnet/sqlclient/blob/master/release-notes/2.1)) | Closed |
+| Microsoft.Data.SqlClient v3.0 | GA (General Availability) estimated for May 2021 | [SqlClient 3.0.0](https://github.com/dotnet/SqlClient/projects/7) |
> Note: Dates are calendar year (as opposed to fiscal year).
diff --git a/tools/props/Versions.props b/tools/props/Versions.props
index eda4a98a5b..d04745707f 100644
--- a/tools/props/Versions.props
+++ b/tools/props/Versions.props
@@ -7,7 +7,7 @@
2.0.20168.41.0.0-beta.18578.2
- 2.1.0-dev
+ 3.0.0-dev$(NugetPackageVersion)
From 45a66966fbda158cb5f97642526d8e0f9de543e9 Mon Sep 17 00:00:00 2001
From: Cheena Malhotra
Date: Tue, 12 Jan 2021 15:23:03 -0800
Subject: [PATCH 019/509] Fix | Fix issue connecting with instance name from
Unix environment (#870)
---
.../netcore/src/Microsoft/Data/SqlClient/SNI/SNIProxy.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIProxy.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIProxy.cs
index 8038220844..c35d4b64ac 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIProxy.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIProxy.cs
@@ -685,7 +685,7 @@ private bool InferConnectionDetails()
int commaIndex = _dataSourceAfterTrimmingProtocol.IndexOf(CommaSeparator);
- int backSlashIndex = _dataSourceAfterTrimmingProtocol.IndexOf(PipeBeginning);
+ int backSlashIndex = _dataSourceAfterTrimmingProtocol.IndexOf(BackSlashCharacter);
// Check the parameters. The parameters are Comma separated in the Data Source. The parameter we really care about is the port
// If Comma exists, the try to get the port number
From b2c28a8b1416acb01faae6fda66a6c5b7dc8e4b8 Mon Sep 17 00:00:00 2001
From: Cheena Malhotra
Date: Wed, 13 Jan 2021 09:59:33 -0800
Subject: [PATCH 020/509] [.NET Core] Event source traces revision - Part 1 & 2
(#867)
---
.../Data/SqlClient/LocalDBAPI.Common.cs | 6 +-
.../Data/SqlClient/LocalDBAPI.Windows.cs | 2 +-
.../Microsoft/Data/SqlClient/SqlBulkCopy.cs | 8 +-
.../Microsoft/Data/SqlClient/SqlCommand.cs | 152 +++++++++---------
.../Microsoft/Data/SqlClient/SqlCommandSet.cs | 8 +-
.../Microsoft/Data/SqlClient/SqlConnection.cs | 50 +++---
.../Data/SqlClient/SqlConnectionFactory.cs | 4 +-
.../SqlConnectionPoolGroupProviderInfo.cs | 8 +-
.../Data/SqlClient/SqlDataAdapter.cs | 6 +-
.../Microsoft/Data/SqlClient/SqlDataReader.cs | 50 +++---
.../Data/SqlClient/SqlDelegatedTransaction.cs | 30 ++--
.../SqlClient/SqlDependencyUtils.AppDomain.cs | 8 +-
.../src/Microsoft/Data/SqlClient/SqlError.cs | 4 +-
.../Data/SqlClient/SqlInternalConnection.cs | 41 +++--
.../Data/SqlClient/SqlInternalTransaction.cs | 18 +--
.../Data/SqlClient/SqlTransaction.cs | 20 +--
.../TdsParserStateObjectFactory.Windows.cs | 4 +-
.../Data/SqlTypes/SqlFileStream.Windows.cs | 24 ++-
.../Data/SqlClient/SqlClientEventSource.cs | 48 +++++-
19 files changed, 266 insertions(+), 225 deletions(-)
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/LocalDBAPI.Common.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/LocalDBAPI.Common.cs
index f072900b6e..f30ddf4243 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/LocalDBAPI.Common.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/LocalDBAPI.Common.cs
@@ -38,7 +38,7 @@ private static LocalDBFormatMessageDelegate LocalDBFormatMessage
{
// SNI checks for LocalDBFormatMessage during DLL loading, so it is practically impossible to get this error.
int hResult = Marshal.GetLastWin32Error();
- SqlClientEventSource.Log.TryTraceEvent(" GetProcAddress for LocalDBFormatMessage error 0x{0}", hResult);
+ SqlClientEventSource.Log.TryTraceEvent("LocalDBAPI.LocalDBFormatMessage> GetProcAddress for LocalDBFormatMessage error 0x{0}", hResult);
throw CreateLocalDBException(errorMessage: Strings.LocalDB_MethodNotFound);
}
s_localDBFormatMessage = Marshal.GetDelegateForFunctionPointer(functionAddr);
@@ -68,14 +68,14 @@ internal static string GetLocalDBMessage(int hrCode)
uint len = (uint)buffer.Capacity;
- // First try for current culture
+ // First try for current culture
int hResult = LocalDBFormatMessage(hrLocalDB: hrCode, dwFlags: const_LOCALDB_TRUNCATE_ERR_MESSAGE, dwLanguageId: (uint)CultureInfo.CurrentCulture.LCID,
buffer: buffer, buflen: ref len);
if (hResult >= 0)
return buffer.ToString();
else
{
- // Message is not available for current culture, try default
+ // Message is not available for current culture, try default
buffer = new StringBuilder((int)const_ErrorMessageBufferSize);
len = (uint)buffer.Capacity;
hResult = LocalDBFormatMessage(hrLocalDB: hrCode, dwFlags: const_LOCALDB_TRUNCATE_ERR_MESSAGE, dwLanguageId: 0 /* thread locale with fallback to English */,
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/LocalDBAPI.Windows.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/LocalDBAPI.Windows.cs
index 6334e5873d..6ec654e3bf 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/LocalDBAPI.Windows.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/LocalDBAPI.Windows.cs
@@ -24,7 +24,7 @@ private static IntPtr UserInstanceDLLHandle
SNINativeMethodWrapper.SNIQueryInfo(SNINativeMethodWrapper.QTypes.SNI_QUERY_LOCALDB_HMODULE, ref s_userInstanceDLLHandle);
if(s_userInstanceDLLHandle != IntPtr.Zero)
{
- SqlClientEventSource.Log.TryTraceEvent(" LocalDB - handle obtained");
+ SqlClientEventSource.Log.TryTraceEvent("LocalDBAPI.UserInstanceDLLHandle | LocalDB - handle obtained");
}
else
{
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlBulkCopy.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlBulkCopy.cs
index 344d517618..b7939ece6b 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlBulkCopy.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlBulkCopy.cs
@@ -553,8 +553,8 @@ private string CreateInitialQuery()
private Task CreateAndExecuteInitialQueryAsync(out BulkCopySimpleResultSet result)
{
string TDSCommand = CreateInitialQuery();
- SqlClientEventSource.Log.TryTraceEvent(" Initial Query: '{0}'", TDSCommand);
- SqlClientEventSource.Log.TryCorrelationTraceEvent(" ObjectID {0}, ActivityID {1}", ObjectID, ActivityCorrelator.Current);
+ SqlClientEventSource.Log.TryTraceEvent("SqlBulkCopy.CreateAndExecuteInitialQueryAsync | Info | Initial Query: '{0}'", TDSCommand);
+ SqlClientEventSource.Log.TryCorrelationTraceEvent("SqlBulkCopy.CreateAndExecuteInitialQueryAsync | Info | Correlation | Object Id {0}, Activity Id {1}", ObjectID, ActivityCorrelator.Current);
Task executeTask = _parser.TdsExecuteSQLBatch(TDSCommand, this.BulkCopyTimeout, null, _stateObj, sync: !_isAsyncBulkCopy, callerHasConnectionLock: true);
if (executeTask == null)
@@ -852,7 +852,7 @@ private string TryGetOrderHintText(HashSet destColumnNames)
private Task SubmitUpdateBulkCommand(string TDSCommand)
{
- SqlClientEventSource.Log.TryCorrelationTraceEvent(" ObjectID{0}, ActivityID {1}", ObjectID, ActivityCorrelator.Current);
+ SqlClientEventSource.Log.TryCorrelationTraceEvent("SqlBulkCopy.SubmitUpdateBulkCommand | Info | Correlation | Object Id {0}, Activity Id {1}", ObjectID, ActivityCorrelator.Current);
Task executeTask = _parser.TdsExecuteSQLBatch(TDSCommand, this.BulkCopyTimeout, null, _stateObj, sync: !_isAsyncBulkCopy, callerHasConnectionLock: true);
if (executeTask == null)
@@ -2368,7 +2368,7 @@ private void CheckAndRaiseNotification()
// It's also the user's chance to cause an exception.
_stateObj.BcpLock = true;
abortOperation = FireRowsCopiedEvent(_rowsCopied);
- SqlClientEventSource.Log.TryTraceEvent("");
+ SqlClientEventSource.Log.TryTraceEvent("SqlBulkCopy.CheckAndRaiseNotification | Info | Rows Copied {0}", _rowsCopied);
// In case the target connection is closed accidentally.
if (ConnectionState.Open != _connection.State)
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs
index 10d5064a87..2f883c19d2 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs
@@ -103,7 +103,7 @@ protected override void AfterCleared(SqlCommand owner)
/// Internal flag for testing purposes that forces all queries to internally end async calls.
///
private static bool _forceInternalEndQuery = false;
-#endif
+#endif
private static readonly SqlDiagnosticListener _diagnosticListener = new SqlDiagnosticListener(SqlClientDiagnosticListenerExtensions.DiagnosticListenerName);
private bool _parentOperationStarted = false;
@@ -172,7 +172,7 @@ internal bool InPrepare
///
/// Return if column encryption setting is enabled.
- /// The order in the below if is important since _activeConnection.Parser can throw if the
+ /// The order in the below if is important since _activeConnection.Parser can throw if the
/// underlying tds connection is closed and we don't want to change the behavior for folks
/// not trying to use transparent parameter encryption i.e. who don't use (SqlCommandColumnEncryptionSetting.Enabled or _activeConnection.IsColumnEncryptionSettingEnabled) here.
///
@@ -312,7 +312,7 @@ private CachedAsyncState cachedAsyncState
// Volatile bool used to synchronize with cancel thread the state change of an executing
// command going from pre-processing to obtaining a stateObject. The cancel synchronization
- // we require in the command is only from entering an Execute* API to obtaining a
+ // we require in the command is only from entering an Execute* API to obtaining a
// stateObj. Once a stateObj is successfully obtained, cancel synchronization is handled
// by the stateObject.
private volatile bool _pendingCancel;
@@ -438,7 +438,7 @@ private SqlCommand(SqlCommand from) : this()
}
catch (Exception)
{
- // we do not really care about errors in unprepare (may be the old connection went bad)
+ // we do not really care about errors in unprepare (may be the old connection went bad)
}
finally
{
@@ -449,7 +449,7 @@ private SqlCommand(SqlCommand from) : this()
}
}
_activeConnection = value;
- SqlClientEventSource.Log.TryTraceEvent(" {0}, {1}", ObjectID, value?.ObjectID);
+ SqlClientEventSource.Log.TryTraceEvent("SqlCommand.Set_Connection | API | ObjectId {0}, Client Connection Id {1}, SPID {2}", ObjectID, value?.ClientConnectionId, value?.ServerProcessId);
}
}
@@ -483,9 +483,9 @@ public SqlNotificationRequest Notification
}
set
{
- SqlClientEventSource.Log.TryTraceEvent(" {0}", ObjectID);
_sqlDep = null;
_notification = value;
+ SqlClientEventSource.Log.TryTraceEvent("SqlCommand.Set_Notification | API | Object Id {0}", ObjectID);
}
}
@@ -527,8 +527,8 @@ internal SqlStatistics Statistics
throw SQL.CannotModifyPropertyAsyncOperationInProgress();
}
}
- SqlClientEventSource.Log.TryTraceEvent(" {0}", ObjectID);
_transaction = value;
+ SqlClientEventSource.Log.TryTraceEvent("SqlCommand.Set_Transaction | API | Object Id {0}, Internal Transaction Id {1}, Client Connection Id {2}, SPID {3}", ObjectID, value?.InternalTransaction?.TransactionId, Connection?.ClientConnectionId, Connection?.ServerProcessId);
}
}
@@ -542,6 +542,7 @@ override protected DbTransaction DbTransaction
set
{
Transaction = (SqlTransaction)value;
+ SqlClientEventSource.Log.TryTraceEvent("SqlCommand.Set_DbTransaction | API | Object Id {0}, Client Connection Id {1}, SPID {2}", ObjectID, Connection?.ClientConnectionId, Connection?.ServerProcessId);
}
}
@@ -555,12 +556,12 @@ override public string CommandText
}
set
{
- SqlClientEventSource.Log.TryTraceEvent(" {0}, String Value = '{1}'", ObjectID, value);
if (_commandText != value)
{
PropertyChanging();
_commandText = value;
}
+ SqlClientEventSource.Log.TryTraceEvent("SqlCommand.Set_CommandText | API | Object Id {0}, String Value = '{1}', Client Connection Id {2}, SPID {3}", ObjectID, value, Connection?.ClientConnectionId, Connection?.ServerProcessId);
}
}
@@ -576,7 +577,6 @@ override public int CommandTimeout
}
set
{
- SqlClientEventSource.Log.TryTraceEvent(" {0}, {1}", ObjectID, value);
if (value < 0)
{
throw ADP.InvalidCommandTimeout(value);
@@ -586,6 +586,7 @@ override public int CommandTimeout
PropertyChanging();
_commandTimeout = value;
}
+ SqlClientEventSource.Log.TryTraceEvent("SqlCommand.Set_CommandTimeout | API | ObjectId {0}, Command Timeout value {1}, Client Connection Id {2}, SPID {3}", ObjectID, value, Connection?.ClientConnectionId, Connection?.ServerProcessId);
}
}
@@ -617,7 +618,6 @@ override public CommandType CommandType
}
set
{
- SqlClientEventSource.Log.TryTraceEvent(" {0}, {1}{2}", ObjectID, (int)value, _commandType);
if (_commandType != value)
{
switch (value)
@@ -632,6 +632,7 @@ override public CommandType CommandType
default:
throw ADP.InvalidCommandType(value);
}
+ SqlClientEventSource.Log.TryTraceEvent("SqlCommand.Set_CommandType | API | ObjectId {0}, Command type value {1}, Client Connection Id {2}, SPID {3}", ObjectID, (int)value, Connection?.ClientConnectionId, Connection?.ServerProcessId);
}
}
}
@@ -697,6 +698,7 @@ override public UpdateRowSource UpdatedRowSource
default:
throw ADP.InvalidUpdateRowSource(value);
}
+ SqlClientEventSource.Log.TryTraceEvent("SqlCommand.UpdatedRowSource | API | ObjectId {0}, Updated row source value {1}, Client Connection Id {2}, SPID {3}", ObjectID, (int)value, Connection?.ClientConnectionId, Connection?.ServerProcessId);
}
}
@@ -722,7 +724,7 @@ internal void OnStatementCompleted(int recordCount)
{
try
{
- SqlClientEventSource.Log.TryTraceEvent(" {0}, recordCount={1}", ObjectID, recordCount);
+ SqlClientEventSource.Log.TryTraceEvent("SqlCommand.OnStatementCompleted | Info | ObjectId {0}, Record Count {1}, Client Connection Id {2}, SPID {3}", ObjectID, recordCount, Connection?.ClientConnectionId, Connection?.ServerProcessId);
handler(this, new StatementCompletedEventArgs(recordCount));
}
catch (Exception e)
@@ -749,22 +751,17 @@ override public void Prepare()
_pendingCancel = false;
SqlStatistics statistics = null;
- long scopeID = SqlClientEventSource.Log.TryScopeEnterEvent(" {0}", ObjectID);
- SqlClientEventSource.Log.TryCorrelationTraceEvent(" ObjectID {0}, ActivityID {1}", ObjectID, ActivityCorrelator.Current);
+ long scopeID = SqlClientEventSource.Log.TryScopeEnterEvent("SqlCommand.Prepare | API | Object Id {0}", ObjectID);
+ SqlClientEventSource.Log.TryCorrelationTraceEvent("SqlCommand.Prepare | API | Correlation | Object Id {0}, ActivityID {1}, Client Connection Id {2}, SPID {3}", ObjectID, ActivityCorrelator.Current, Connection?.ClientConnectionId, Connection?.ServerProcessId);
try
{
statistics = SqlStatistics.StartTimer(Statistics);
// only prepare if batch with parameters
- if (
- this.IsPrepared && !this.IsDirty
+ if (this.IsPrepared && !this.IsDirty
|| (this.CommandType == CommandType.StoredProcedure)
- || (
- (System.Data.CommandType.Text == this.CommandType)
- && (0 == GetParameterCount(_parameters))
- )
-
- )
+ || ((System.Data.CommandType.Text == this.CommandType)
+ && (0 == GetParameterCount(_parameters))))
{
if (null != Statistics)
{
@@ -855,6 +852,9 @@ internal void Unprepare()
Debug.Assert(_activeConnection != null, "must have an open connection to UnPrepare");
Debug.Assert(false == _inPrepare, "_inPrepare should be false!");
_execType = EXECTYPE.PREPAREPENDING;
+
+ SqlClientEventSource.Log.TryTraceEvent("SqlCommand.UnPrepare | Info | Object Id {0}, Current Prepared Handle {1}", ObjectID, _prepareHandle);
+
// Don't zero out the handle because we'll pass it in to sp_prepexec on the next prepare
// Unless the close count isn't the same as when we last prepared
if ((_activeConnection.CloseCount != _preparedConnectionCloseCount) || (_activeConnection.ReconnectCount != _preparedConnectionReconnectCount))
@@ -864,7 +864,7 @@ internal void Unprepare()
}
_cachedMetaData = null;
- SqlClientEventSource.Log.TryTraceEvent(" {0}, Command unprepared.", ObjectID);
+ SqlClientEventSource.Log.TryTraceEvent("SqlCommand.UnPrepare | Info | Object Id {0}, Command unprepared.", ObjectID);
}
// Cancel is supposed to be multi-thread safe.
@@ -874,8 +874,9 @@ internal void Unprepare()
///
override public void Cancel()
{
- long scopeID = SqlClientEventSource.Log.TryScopeEnterEvent(" {0}", ObjectID);
- SqlClientEventSource.Log.TryCorrelationTraceEvent(" ObjectID {0}, ActivityID {1}", ObjectID, ActivityCorrelator.Current);
+ long scopeID = SqlClientEventSource.Log.TryScopeEnterEvent("SqlCommand.Cancel | API | Object Id {0}", ObjectID);
+ SqlClientEventSource.Log.TryCorrelationTraceEvent("SqlCommand.Cancel | API | Correlation | Object Id {0}, Activity Id {1}, Client Connection Id {2}, SPID {3}, Command Text '{4}'", ObjectID, ActivityCorrelator.Current, Connection?.ClientConnectionId, Connection?.ServerProcessId, CommandText);
+
SqlStatistics statistics = null;
try
{
@@ -907,7 +908,7 @@ override public void Cancel()
}
// The lock here is to protect against the command.cancel / connection.close race condition
- // The SqlInternalConnectionTds is set to OpenBusy during close, once this happens the cast below will fail and
+ // The SqlInternalConnectionTds is set to OpenBusy during close, once this happens the cast below will fail and
// the command will no longer be cancelable. It might be desirable to be able to cancel the close operation, but this is
// outside of the scope of Whidbey RTM. See (SqlConnection::Close) for other lock.
lock (connection)
@@ -929,7 +930,7 @@ override public void Cancel()
// Before attempting actual cancel, set the _pendingCancel flag to false.
// This denotes to other thread before obtaining stateObject from the
// session pool that there is another thread wishing to cancel.
- // The period in question is between entering the ExecuteAPI and obtaining
+ // The period in question is between entering the ExecuteAPI and obtaining
// a stateObject.
_pendingCancel = true;
@@ -990,8 +991,8 @@ override public object ExecuteScalar()
SqlStatistics statistics = null;
- long scopeID = SqlClientEventSource.Log.TryScopeEnterEvent(" {0}", ObjectID);
- SqlClientEventSource.Log.TryCorrelationTraceEvent(" ObjectID{0}, ActivityID {1}", ObjectID, ActivityCorrelator.Current);
+ long scopeID = SqlClientEventSource.Log.TryScopeEnterEvent("SqlCommand.ExecuteScalar | API | ObjectId {0}", ObjectID);
+ SqlClientEventSource.Log.TryCorrelationTraceEvent("SqlCommand.ExecuteScalar | API | Correlation | Object Id {0}, Activity Id {1}, Client Connection Id {2}, SPID {3}, Command Text '{4}'", ObjectID, ActivityCorrelator.Current, Connection?.ClientConnectionId, Connection?.ServerProcessId, CommandText);
Exception e = null;
bool success = false;
@@ -1074,8 +1075,8 @@ override public int ExecuteNonQuery()
SqlStatistics statistics = null;
- long scopeID = SqlClientEventSource.Log.TryScopeEnterEvent(" {0}", ObjectID);
- SqlClientEventSource.Log.TryCorrelationTraceEvent(" ObjectID {0}, ActivityID {1}", ObjectID, ActivityCorrelator.Current);
+ long scopeID = SqlClientEventSource.Log.TryScopeEnterEvent("SqlCommand.ExecuteNonQuery | API | Object Id {0}", ObjectID);
+ SqlClientEventSource.Log.TryCorrelationTraceEvent("SqlCommand.ExecuteNonQuery | API | Correlation | Object Id {0}, ActivityID {1}, Client Connection Id {2}, SPID {3}, Command Text {4}", ObjectID, ActivityCorrelator.Current, Connection?.ClientConnectionId, Connection?.ServerProcessId, CommandText);
Exception e = null;
try
{
@@ -1104,21 +1105,18 @@ override public int ExecuteNonQuery()
}
///
- public IAsyncResult BeginExecuteNonQuery()
- {
- // BeginExecuteNonQuery will track ExecutionTime for us
- return BeginExecuteNonQuery(null, null);
- }
+ public IAsyncResult BeginExecuteNonQuery() => BeginExecuteNonQuery(null, null); // BeginExecuteNonQuery will track ExecutionTime for us
///
public IAsyncResult BeginExecuteNonQuery(AsyncCallback callback, object stateObject)
{
- SqlClientEventSource.Log.TryCorrelationTraceEvent(" ObjectID {0}, ActivityID {1}", ObjectID, ActivityCorrelator.Current);
+ SqlClientEventSource.Log.TryCorrelationTraceEvent("SqlCommand.BeginExecuteNonQuery | API | Correlation | Object Id {0}, Activity Id {1}, Client Connection Id {2}, SPID {3}, Command Text '{4}'", ObjectID, ActivityCorrelator.Current, Connection?.ClientConnectionId, Connection?.ServerProcessId, CommandText);
return BeginExecuteNonQueryInternal(0, callback, stateObject, 0, inRetry: false);
}
private IAsyncResult BeginExecuteNonQueryAsync(AsyncCallback callback, object stateObject)
{
+ SqlClientEventSource.Log.TryCorrelationTraceEvent("SqlCommand.BeginExecuteNonQueryAsync | API | Correlation | Object Id {0}, Activity Id {1}, Client Connection Id {2}, SPID {3}, Command Text '{4}'", ObjectID, ActivityCorrelator.Current, Connection?.ClientConnectionId, Connection?.ServerProcessId, CommandText);
return BeginExecuteNonQueryInternal(0, callback, stateObject, CommandTimeout, inRetry: false, asyncWrite: true);
}
@@ -1291,7 +1289,7 @@ private void WaitForAsyncResults(IAsyncResult asyncResult, bool isInternal)
}
// If this is an internal command we will decrement the count when the End method is actually called by the user.
- // If we are using Column Encryption and the previous task failed, the async count should have already been fixed up.
+ // If we are using Column Encryption and the previous task failed, the async count should have already been fixed up.
// There is a generic issue in how we handle the async count because:
// a) BeginExecute might or might not clean it up on failure.
// b) In EndExecute, we check the task state before waiting and throw if it's failed, whereas if we wait we will always adjust the count.
@@ -1310,7 +1308,7 @@ public int EndExecuteNonQuery(IAsyncResult asyncResult)
}
finally
{
- SqlClientEventSource.Log.TryCorrelationTraceEvent(" ObjectID {0}, ActivityID {1}", ObjectID, ActivityCorrelator.Current);
+ SqlClientEventSource.Log.TryCorrelationTraceEvent("SqlCommand.EndExecuteNonQuery | API | Correlation | Object Id {0}, Activity Id {1}, Client Connection Id {2}, SPID {3}, Command Text '{4}'", ObjectID, ActivityCorrelator.Current, Connection?.ClientConnectionId, Connection?.ServerProcessId, CommandText);
}
}
@@ -1329,7 +1327,7 @@ private void ThrowIfReconnectionHasBeenCanceled()
///
public int EndExecuteNonQueryAsync(IAsyncResult asyncResult)
{
- SqlClientEventSource.Log.TryCorrelationTraceEvent(" ObjectID {0}, ActivityID {1}", ObjectID, ActivityCorrelator.Current);
+ SqlClientEventSource.Log.TryCorrelationTraceEvent("SqlCommand.EndExecuteNonQueryAsync | Info | Correlation | Object Id {0}, Activity Id {1}, Client Connection Id {2}, SPID {3}, Command Text '{4}'", ObjectID, ActivityCorrelator.Current, Connection?.ClientConnectionId, Connection?.ServerProcessId, CommandText);
Debug.Assert(!_internalEndExecuteInitiated || _stateObj == null);
Exception asyncException = ((Task)asyncResult).Exception;
@@ -1380,7 +1378,7 @@ private int EndExecuteNonQueryInternal(IAsyncResult asyncResult)
sqlExceptionNumber = e.Number;
_cachedAsyncState?.ResetAsyncState();
- // SqlException is always catchable
+ // SqlException is always catchable
ReliablePutStateObject();
throw;
}
@@ -1415,7 +1413,7 @@ private object InternalEndExecuteNonQuery(IAsyncResult asyncResult, bool isInter
bool processFinallyBlock = true;
try
{
- // If this is not for internal usage, notify the dependency.
+ // If this is not for internal usage, notify the dependency.
// If we have already initiated the end internally, the reader should be ready, so just return the rows affected.
if (!isInternal)
{
@@ -1507,7 +1505,8 @@ private Task InternalExecuteNonQuery(TaskCompletionSource