Пример #1
0
        public void UDTParams_InputOutput()
        {
            string spInsertCity = DataTestUtility.GetUniqueNameForSqlServer("spUdtTest2_InsertCity");
            string tableName    = DataTestUtility.GetUniqueNameForSqlServer("UdtTest2");

            using (SqlConnection conn = new SqlConnection(_connStr))
            {
                conn.Open();

                SqlTransaction tx  = conn.BeginTransaction();
                SqlCommand     cmd = conn.CreateCommand();

                cmd.Transaction = tx;

                // create the table
                cmd.CommandText = "create table " + tableName + " (name sysname,location Point)";
                cmd.ExecuteNonQuery();

                // create sp
                cmd.CommandText = "create proc " + spInsertCity + "(@name sysname, @location Point OUTPUT)" + " AS insert into " + tableName + " values (@name, @location)";
                cmd.ExecuteNonQuery();
                try
                {
                    cmd.CommandText = spInsertCity;
                    cmd.CommandType = CommandType.StoredProcedure;

                    SqlParameter pName = cmd.Parameters.Add("@name", SqlDbType.NVarChar, 20);
                    SqlParameter p     = cmd.Parameters.Add("@location", SqlDbType.Udt);

                    Point pt = new Point(100, 100);
                    p.UdtTypeName = "Point";
                    p.Direction   = ParameterDirection.InputOutput;
                    p.Value       = pt;
                    pName.Value   = "newcity";

                    cmd.ExecuteNonQuery();
                    DataTestUtility.AssertEqualsWithDescription(
                        "141.42135623731", ((Point)(p.Value)).Distance().ToString(),
                        "Unexpected distance value.");
                    DataTestUtility.AssertEqualsWithDescription(
                        "141.42135623731", ((Point)(p.Value)).Distance().ToString(),
                        "Unexpected distance value after reading out param again.");

                    cmd.Parameters.Clear();
                    cmd.CommandType = CommandType.Text;
                    cmd.CommandText = "select * from " + tableName;
                    using (SqlDataReader reader = cmd.ExecuteReader())
                    {
                        string expectedValue = "   newcity, p.X = 100, p.Y = 100, p.Distance() = 141.42135623731" + Environment.NewLine;
                        DataTestUtility.AssertEqualsWithDescription(
                            expectedValue, UdtTestHelpers.DumpReaderString(reader, false),
                            "Unexpected reader dump string.");
                    }
                }
                finally
                {
                    tx.Rollback();
                }
            }
        }
Пример #2
0
        /// <summary>
        /// Round trip sql_variant value using TVP.
        /// </summary>
        private static void SendVariantTvp(object paramValue, string expectedTypeName, string expectedBaseTypeName)
        {
            string tvpTypeName = DataTestUtility.GetUniqueNameForSqlServer("tvpVariant");

            using (SqlConnection connTvp = new SqlConnection(s_connStr))
            {
                connTvp.Open();

                ExecuteSQL(connTvp, "create type dbo.{0} as table (f1 sql_variant)", tvpTypeName);
                try
                {
                    // Send TVP using SqlMetaData.
                    SqlMetaData[] metadata = new SqlMetaData[1];
                    metadata[0] = new SqlMetaData("f1", SqlDbType.Variant);
                    SqlDataRecord[] record = new SqlDataRecord[1];
                    record[0] = new SqlDataRecord(metadata);
                    record[0].SetValue(0, paramValue);

                    using (SqlCommand cmd = connTvp.CreateCommand())
                    {
                        cmd.CommandText = "select f1, sql_variant_property(f1,'BaseType') as BaseType from @tvpParam";
                        SqlParameter p = cmd.Parameters.AddWithValue("@tvpParam", record);
                        p.SqlDbType = SqlDbType.Structured;
                        p.TypeName  = string.Format("dbo.{0}", tvpTypeName);
                        using (SqlDataReader dr = cmd.ExecuteReader())
                        {
                            VerifyReader("SendVariantTvp[SqlMetaData]", dr, expectedTypeName, expectedBaseTypeName);
                        }
                    }

                    // Send TVP using SqlDataReader.
                    using (SqlDataReader dr = GetReaderForVariant(paramValue, false))
                    {
                        using (SqlCommand cmd = connTvp.CreateCommand())
                        {
                            cmd.CommandText = "select f1, sql_variant_property(f1,'BaseType') as BaseType from @tvpParam";
                            SqlParameter p = cmd.Parameters.AddWithValue("@tvpParam", dr);
                            p.SqlDbType = SqlDbType.Structured;
                            p.TypeName  = string.Format("dbo.{0}", tvpTypeName);
                            using (SqlDataReader dr2 = cmd.ExecuteReader())
                            {
                                VerifyReader("SendVariantTvp[SqlDataReader]", dr2, expectedTypeName, expectedBaseTypeName);
                            }
                        }
                    }
                }
                finally
                {
                    // Cleanup tvp type.
                    ExecuteSQL(connTvp, "drop type {0}", tvpTypeName);
                }
            }
        }
Пример #3
0
        public void UDTParams_NullInput()
        {
            string spInsertCustomer = DataTestUtility.GetUniqueNameForSqlServer("spUdtTest2_InsertCustomer");
            string tableName        = DataTestUtility.GetUniqueNameForSqlServer("UdtTest2_Customer");

            using (SqlConnection conn = new SqlConnection(_connStr))
                using (SqlCommand cmd = conn.CreateCommand())
                {
                    conn.Open();

                    cmd.Transaction = conn.BeginTransaction();
                    cmd.CommandText = "create table " + tableName + " (name nvarchar(30), address Address)";
                    cmd.ExecuteNonQuery();
                    cmd.CommandText = "create proc " + spInsertCustomer + "(@name nvarchar(30), @addr Address OUTPUT)" + " AS insert into " + tableName + " values (@name, @addr)";
                    cmd.ExecuteNonQuery();
                    try
                    {
                        cmd.CommandText = spInsertCustomer;
                        cmd.CommandType = CommandType.StoredProcedure;

                        SqlParameter pName = cmd.Parameters.Add("@name", SqlDbType.NVarChar, 20);
                        SqlParameter p     = cmd.Parameters.Add("@addr", SqlDbType.Udt);

                        p.UdtTypeName = "UdtTestDb.dbo.Address";
                        p.Value       = null;
                        pName.Value   = "john";

                        string spInsertCustomerNoBrackets = spInsertCustomer;
                        if (spInsertCustomer.StartsWith("[") && spInsertCustomer.EndsWith("]"))
                        {
                            spInsertCustomerNoBrackets = spInsertCustomer.Substring(1, spInsertCustomer.Length - 2);
                        }
                        string errorMsg = "Procedure or function '" + spInsertCustomerNoBrackets + "' expects parameter '@addr', which was not supplied.";

                        DataTestUtility.AssertThrowsWrapper <SqlException>(
                            () => cmd.ExecuteNonQuery(),
                            errorMsg);
                    }
                    finally
                    {
                        cmd.Transaction.Rollback();
                    }
                }
        }
Пример #4
0
        public void UDTParams_TypedNull()
        {
            string spInsertCustomer = DataTestUtility.GetUniqueNameForSqlServer("spUdtTest2_InsertCustomer");
            string tableName        = DataTestUtility.GetUniqueNameForSqlServer("UdtTest2_Customer");

            using (SqlConnection conn = new SqlConnection(_connStr))
                using (SqlCommand cmd = conn.CreateCommand())
                {
                    conn.Open();

                    cmd.Transaction = conn.BeginTransaction();
                    cmd.CommandText = "create table " + tableName + " (name nvarchar(30), address Address)";
                    cmd.ExecuteNonQuery();

                    // create proc sp_insert_customer(@name nvarchar(30), @addr Address OUTPUT)
                    // AS
                    // insert into customers values (@name, @addr)
                    cmd.CommandText = "create proc " + spInsertCustomer + " (@name nvarchar(30), @addr Address OUTPUT)" + " AS insert into " + tableName + " values (@name, @addr)";
                    cmd.ExecuteNonQuery();
                    try
                    {
                        cmd.CommandText = spInsertCustomer;
                        cmd.CommandType = CommandType.StoredProcedure;

                        Address      addr  = Address.Parse("123 baker st || Redmond");
                        SqlParameter pName = cmd.Parameters.Add("@name", SqlDbType.NVarChar, 20);
                        SqlParameter p     = cmd.Parameters.Add("@addr", SqlDbType.Udt);

                        p.UdtTypeName = "UdtTestDb.dbo.Address";
                        p.Value       = Address.Null;
                        pName.Value   = "john";
                        cmd.ExecuteNonQuery();

                        DataTestUtility.AssertEqualsWithDescription(
                            Address.Null.ToString(), p.Value.ToString(),
                            "Unexpected parameter value.");
                    }
                    finally
                    {
                        cmd.Transaction.Rollback();
                    }
                }
        }
Пример #5
0
        public void UDTParams_Invalid2()
        {
            string spInsertCustomer = DataTestUtility.GetUniqueNameForSqlServer("spUdtTest2_InsertCustomer");
            string tableName        = DataTestUtility.GetUniqueNameForSqlServer("UdtTest2");

            using (SqlConnection conn = new SqlConnection(_connStr))
                using (SqlCommand cmd = conn.CreateCommand())
                {
                    conn.Open();

                    cmd.Transaction = conn.BeginTransaction();
                    cmd.CommandText = "create table " + tableName + " (name nvarchar(30), address Address)";
                    cmd.ExecuteNonQuery();
                    cmd.CommandText = "create proc " + spInsertCustomer + "(@name nvarchar(30), @addr Address OUTPUT)" + " AS insert into " + tableName + " values (@name, @addr)";
                    cmd.ExecuteNonQuery();
                    try
                    {
                        cmd.CommandText = spInsertCustomer;
                        cmd.CommandType = CommandType.StoredProcedure;

                        SqlParameter pName = cmd.Parameters.Add("@fname", SqlDbType.NVarChar, 20);
                        SqlParameter p     = cmd.Parameters.Add("@addr", SqlDbType.Udt);

                        Address addr = Address.Parse("customer whose name is address");
                        p.UdtTypeName = "UdtTestDb.dbo.Address";
                        p.Value       = addr;
                        pName.Value   = addr;

                        DataTestUtility.AssertThrowsWrapper <InvalidCastException>(
                            () => cmd.ExecuteReader(),
                            "Failed to convert parameter value from a Address to a String.");
                    }
                    finally
                    {
                        cmd.Transaction.Rollback();
                    }
                }
        }
Пример #6
0
        /// <summary>
        /// Round trip sql_variant value using SqlBulkCopy.
        /// </summary>
        private static void SendVariantBulkCopy(object paramValue, string expectedTypeName, string expectedBaseTypeName)
        {
            string bulkCopyTableName = DataTestUtility.GetUniqueNameForSqlServer("bulkDest");

            // Fetch reader using type.
            using (SqlDataReader dr = GetReaderForVariant(paramValue, false))
            {
                using (SqlConnection connBulk = new SqlConnection(s_connStr))
                {
                    connBulk.Open();

                    ExecuteSQL(connBulk, "create table dbo.{0} (f1 sql_variant)", bulkCopyTableName);
                    try
                    {
                        // Perform bulk copy to target.
                        using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connBulk))
                        {
                            bulkCopy.BulkCopyTimeout      = 60;
                            bulkCopy.BatchSize            = 1;
                            bulkCopy.DestinationTableName = bulkCopyTableName;
                            bulkCopy.WriteToServer(dr);
                        }

                        // Verify target.
                        using (SqlCommand cmd = connBulk.CreateCommand())
                        {
                            cmd.CommandText = string.Format("select f1, sql_variant_property(f1,'BaseType') as BaseType from {0}", bulkCopyTableName);
                            using (SqlDataReader drVerify = cmd.ExecuteReader())
                            {
                                VerifyReader("SendVariantBulkCopy[SqlDataReader]", drVerify, expectedTypeName, expectedBaseTypeName);
                            }
                        }

                        // Truncate target table for next pass.
                        ExecuteSQL(connBulk, "truncate table {0}", bulkCopyTableName);

                        // Send using DataTable as source.
                        DataTable t = new DataTable();
                        t.Columns.Add("f1", typeof(object));
                        t.Rows.Add(new object[] { paramValue });

                        // Perform bulk copy to target.
                        using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connBulk))
                        {
                            bulkCopy.BulkCopyTimeout      = 60;
                            bulkCopy.BatchSize            = 1;
                            bulkCopy.DestinationTableName = bulkCopyTableName;
                            bulkCopy.WriteToServer(t, DataRowState.Added);
                        }

                        // Verify target.
                        using (SqlCommand cmd = connBulk.CreateCommand())
                        {
                            cmd.CommandText = string.Format("select f1, sql_variant_property(f1,'BaseType') as BaseType from {0}", bulkCopyTableName);
                            using (SqlDataReader drVerify = cmd.ExecuteReader())
                            {
                                VerifyReader("SendVariantBulkCopy[DataTable]", drVerify, expectedTypeName, expectedBaseTypeName);
                            }
                        }

                        // Truncate target table for next pass.
                        ExecuteSQL(connBulk, "truncate table {0}", bulkCopyTableName);

                        // Send using DataRow as source.
                        DataRow[] rowToSend = t.Select();

                        // Perform bulk copy to target.
                        using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connBulk))
                        {
                            bulkCopy.BulkCopyTimeout      = 60;
                            bulkCopy.BatchSize            = 1;
                            bulkCopy.DestinationTableName = bulkCopyTableName;
                            bulkCopy.WriteToServer(rowToSend);
                        }

                        // Verify target.
                        using (SqlCommand cmd = connBulk.CreateCommand())
                        {
                            cmd.CommandText = string.Format("select f1, sql_variant_property(f1,'BaseType') as BaseType from {0}", bulkCopyTableName);
                            using (SqlDataReader drVerify = cmd.ExecuteReader())
                            {
                                VerifyReader("SendVariantBulkCopy[DataRow]", drVerify, expectedTypeName, expectedBaseTypeName);
                            }
                        }
                    }
                    finally
                    {
                        // Cleanup target table.
                        ExecuteSQL(connBulk, "drop table {0}", bulkCopyTableName);
                    }
                }
            }
        }
Пример #7
0
        public void RunCopyTest()
        {
            _connStr = (new SqlConnectionStringBuilder(DataTestUtility.TcpConnStr)
            {
                InitialCatalog = DataTestUtility.UdtTestDbName
            }).ConnectionString;
            SqlConnection conn = new SqlConnection(_connStr);

            string cities    = DataTestUtility.GetUniqueNameForSqlServer("UdtBulkCopy_cities");
            string customers = DataTestUtility.GetUniqueNameForSqlServer("UdtBulkCopy_customers");
            string circles   = DataTestUtility.GetUniqueNameForSqlServer("UdtBulkCopy_circles");

            conn.Open();
            try
            {
                ExecuteNonQueryCommand($"create table {cities} (name sysname, location Point)", _connStr);
                ExecuteNonQueryCommand($"create table {customers} (name nvarchar(30), address Address)", _connStr);
                ExecuteNonQueryCommand($"create table {circles} (num int, def Circle)", _connStr);

                string expectedResults =
                    "ColumnName[0] = name" + Environment.NewLine +
                    "DataType[0] = nvarchar" + Environment.NewLine +
                    "FieldType[0] = System.String" + Environment.NewLine +
                    "ColumnName[1] = location" + Environment.NewLine +
                    "DataType[1] = UdtTestDb.dbo.Point" + Environment.NewLine +
                    "FieldType[1] = Point" + Environment.NewLine +
                    "   redmond, p.X =   3, p.Y =   3, p.Distance() = 5" + Environment.NewLine +
                    "  bellevue, p.X =   6, p.Y =   6, p.Distance() = 10" + Environment.NewLine +
                    "   seattle, p.X =  10, p.Y =  10, p.Distance() = 14.866068747318506" + Environment.NewLine +
                    "  portland, p.X =  20, p.Y =  20, p.Distance() = 25" + Environment.NewLine +
                    "        LA, p.X =   3, p.Y =   3, p.Distance() = 5" + Environment.NewLine +
                    "       SFO, p.X =   6, p.Y =   6, p.Distance() = 10" + Environment.NewLine +
                    " beaverton, p.X =  10, p.Y =  10, p.Distance() = 14.866068747318506" + Environment.NewLine +
                    "  new york, p.X =  20, p.Y =  20, p.Distance() = 25" + Environment.NewLine +
                    "     yukon, p.X =  20, p.Y =  20, p.Distance() = 32.01562118716424" + Environment.NewLine;

                CopyTableTest(_connStr, "cities", cities, expectedResults);

                expectedResults =
                    "ColumnName[0] = name" + Environment.NewLine +
                    "DataType[0] = nvarchar" + Environment.NewLine +
                    "FieldType[0] = System.String" + Environment.NewLine +
                    "ColumnName[1] = address" + Environment.NewLine +
                    "DataType[1] = UdtTestDb.dbo.Address" + Environment.NewLine +
                    "FieldType[1] = Address" + Environment.NewLine +
                    "     first, Address 1  Address 2" + Environment.NewLine +
                    "    second, 123 Park Lane  New York" + Environment.NewLine +
                    "     third, 21 Forest grove  Portland" + Environment.NewLine +
                    "    fourth, 34 Lake Blvd  Seattle" + Environment.NewLine +
                    "     fifth, A2 Meadows  Bellevue" + Environment.NewLine;

                CopyTableTest(_connStr, "customers", customers, expectedResults);

                expectedResults =
                    "ColumnName[0] = num" + Environment.NewLine +
                    "DataType[0] = int" + Environment.NewLine +
                    "FieldType[0] = System.Int32" + Environment.NewLine +
                    "ColumnName[1] = def" + Environment.NewLine +
                    "DataType[1] = UdtTestDb.dbo.Circle" + Environment.NewLine +
                    "FieldType[1] = Circle" + Environment.NewLine +
                    "         1, Center = 1,2" + Environment.NewLine +
                    "         2, Center = 3,4" + Environment.NewLine +
                    "         3, Center = 11,23" + Environment.NewLine +
                    "         4, Center = 444,555" + Environment.NewLine +
                    "         5, Center = 1,2" + Environment.NewLine +
                    "         6, Center = 3,4" + Environment.NewLine +
                    "         7, Center = 11,23" + Environment.NewLine +
                    "         8, Center = 444,245" + Environment.NewLine;

                CopyTableTest(_connStr, "circles", circles, expectedResults);
            }
            finally
            {
                ExecuteNonQueryCommand($"drop table {cities}", _connStr);
                ExecuteNonQueryCommand($"drop table {customers}", _connStr);
                ExecuteNonQueryCommand($"drop table {circles}", _connStr);
            }
        }
Пример #8
0
        /// <summary>
        /// Round trip sql_variant value using TVP.
        /// </summary>
        private static void SendVariantTvp(object paramValue, string expectedTypeName, string expectedBaseTypeName)
        {
            string tvpTypeName = DataTestUtility.GetUniqueNameForSqlServer("tvpVariant");

            using (SqlConnection connTvp = new SqlConnection(s_connStr))
            {
                connTvp.Open();

                // Drop and re-create tvp type.
                xsql(connTvp, "if exists(select 1 from sys.types where name='{0}') begin drop type {0} end", tvpTypeName);
                xsql(connTvp, "create type {0} as table (f1 sql_variant)", tvpTypeName);

                // Send TVP using SqlMetaData.
                SqlMetaData[] metadata = new SqlMetaData[1];
                metadata[0] = new SqlMetaData("f1", SqlDbType.Variant);
                SqlDataRecord[] record = new SqlDataRecord[1];
                record[0] = new SqlDataRecord(metadata);
                record[0].SetValue(0, paramValue);

                using (SqlCommand cmd = connTvp.CreateCommand())
                {
                    cmd.CommandText = "select f1, sql_variant_property(f1,'BaseType') as BaseType from @tvpParam";
                    SqlParameter p = cmd.Parameters.AddWithValue("@tvpParam", record);
                    p.SqlDbType = SqlDbType.Structured;
                    p.TypeName  = string.Format("dbo.{0}", tvpTypeName);
                    using (SqlDataReader dr = cmd.ExecuteReader())
                    {
                        VerifyReader("SendVariantTvp[SqlMetaData]", dr, expectedTypeName, expectedBaseTypeName);
                    }
                }

                // Send TVP using DataSet.
                // DEVNOTE: TVPs do not support sql_variant inside DataTable, by design according to tvp spec:
                // 4.3	DbDataReader
                // The only difference or special case for DataTable is that we will not support:
                // 1)	UDT?s
                // 2)	Variant

                /*
                 * DataTable t = new DataTable();
                 * t.Columns.Add("f1", typeof(object));
                 * t.Rows.Add(new object[] { paramValue });
                 * t.AcceptChanges();
                 *
                 * using (SqlCommand cmd = connTvp.CreateCommand())
                 * {
                 *  cmd.CommandText = "select f1, sql_variant_property(@p1,'BaseType') as BaseType from @tvpParam";
                 *  SqlParameter p = cmd.Parameters.AddWithValue("@tvpParam", t);
                 *  p.SqlDbType = SqlDbType.Structured;
                 *  p.TypeName = @"dbo.tvpVariant";
                 *  using (SqlDataReader dr = cmd.ExecuteReader())
                 *  {
                 *      VerifyReader("SendVariantTvp[DataTable]", dr, expectedTypeName, expectedBaseTypeName);
                 *  }
                 * }
                 */

                // Send TVP using SqlDataReader.
                using (SqlDataReader dr = GetReaderForVariant(paramValue, false))
                {
                    using (SqlCommand cmd = connTvp.CreateCommand())
                    {
                        cmd.CommandText = "select f1, sql_variant_property(f1,'BaseType') as BaseType from @tvpParam";
                        SqlParameter p = cmd.Parameters.AddWithValue("@tvpParam", dr);
                        p.SqlDbType = SqlDbType.Structured;
                        p.TypeName  = string.Format("dbo.{0}", tvpTypeName);
                        using (SqlDataReader dr2 = cmd.ExecuteReader())
                        {
                            VerifyReader("SendVariantTvp[SqlDataReader]", dr2, expectedTypeName, expectedBaseTypeName);
                        }
                    }
                }

                // Cleanup tvp type.
                xsql(connTvp, "if exists(select 1 from sys.types where name='{0}') begin drop type {0} end", tvpTypeName);
            }
        }