Reputation: 4187
I have a stored procedure to handle Inserts, Updates and Deletes to a table defined as
CREATE TABLE [dbo].[TestTable](
[Id] [int] PRIMARY KEY NOT NULL,
[Data] [nvarchar](50) NOT NULL,
[ChangeDate] [datetime] NULL)
with the stored prodedure
CREATE PROCEDURE MergeTest
@Testing TestTableType readonly
AS
BEGIN
MERGE INTO Testing as Target
USING (SELECT * FROM @Testing) AS SOURCE
ON (Target.Id = Source.Id)
WHEN MATCHED THEN
UPDATE SET
Target.Data = Source.Data,
Target.ChangeDate = Source.ChangeDate
WHEN NOT MATCHED BY TARGET THEN
INSERT (Data, ChangeDate)
VALUES (Source.Data, Source.ChangeDate)
WHEN NOT MATCHED BY SOURCE THEN
DELETE;
RETURN 0;
END
and the UDT Type as
CREATE TYPE TestTableType AS TABLE(
[Id] [int] PRIMARY KEY NOT NULL,
[Data] [nvarchar](50) NOT NULL,
[ChangeDate] [datetime] NULL)
I am trying to use this structure to do bulk inserts, etc from C#. Using the following code it works:
using (SqlConnection connection = new SqlConnection(@"..."))
{
connection.Open();
DataTable DT = new DataTable();
DT.Columns.Add("Id", typeof(int));
DT.Columns.Add("Data", typeof(string));
DT.Columns.Add("ChangeDate", typeof(DateTime));
for (int i = 0; i < 100000; i++)
{
DT.AddTestRow((i + 1), (i + 1).ToString(), DateTime.Now);
}
using (SqlCommand command = new SqlCommand("MergeTest", connection))
{
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddWithValue("@Testing", DT);
command.ExecuteNonQuery();
}
}
However, when i change the lines
DataTable DT = new DataTable();
DT.Columns.Add("Id", typeof(int));
DT.Columns.Add("Data", typeof(string));
DT.Columns.Add("ChangeDate", typeof(DateTime));
to
DataSet1.TestDataTable DT = new DataSet1.TestDataTable();
which is a strongly typed version of the same DataTable
structure I get a Argument Exception
Error of
No mapping exists from object type TestBulkInsertDataset.DataSet1+TestDataTable to a known managed provider native type.
Is there any way to use a strongly typed DataTable
as a User Defined Table Type Parameter?
Upvotes: 3
Views: 3885
Reputation: 4187
Found the answer. When using strongly typed Data Tables you have to specify the type for the parameter. The parameter line becomes:
var testingparam = command.Parameters.AddWithValue("@Testing", DT);
testingparam.SqlDbType = SqlDbType.Structured;
and then it all works.
Upvotes: 3
Reputation: 13965
Have you tried something like this?
DataSet1.TestDataTable DT = new DataSet1.TestDataTable();
// Fill data table
DataTable DT1 = DT; // DataSet1.TestDataTable should be a subclass of DataTable
using (SqlCommand command = new SqlCommand("MergeTest", connection))
{
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddWithValue("@Testing", DT1);
command.ExecuteNonQuery();
}
If typed DataSets are still subclasses of regular DataSets and DataTables, I would think this would work.
ETA: Since that doesn't work, how about this?
DataSet DS1 = new DataSet();
DS1.Merge(DT, false, MissingSchemaAction.Add);
// etc.
command.Parameters.AddWithValue("@Testing", DS1.Tables[0]);
Assuming that works (and you may have to fiddle with overloads of the Merge method to get the desired result) you'll get a DataTable in your DataSet that has the schema and data of DT, the DataSet1.TestDataTable
, but will just be of type DataTable
.
Upvotes: 1