0

Error is

The type of column 'MemberHId' is not supported. The type is 'SqlHierarchyId'.

In both the server the datatype is same "HierarchyId".

I am just using the ADO.Net.

The assembly is Microsoft.SqlServer.ManagedDTS version- 13.0.0.0 We are using Azure Sql.

Tried with different versions of sql assemblies

 DataTable dt = new DataTable();
 
 dt.Columns.Add("Code", typeof(string));
 dt.Columns.Add("Description", typeof(string));
 dt.Columns.Add("NodeId", typeof(int));
 dt.Columns.Add("MemberHId", typeof(SqlHierarchyId));
 dt.Columns.Add("Level", typeof(int));
                   
//Getting the data from serverAPI which is returning the data in the columns without null records.
 dt=apicall();

 SqlParameter returnParameter = cmd.Parameters.Add("RetVal", SqlDbType.Int);
 returnParameter.Direction = ParameterDirection.ReturnValue;
                
 cmd.CommandType = CommandType.StoredProcedure;
 cmd.CommandText = spName;
 cmd.Parameters.AddWithValue("@MemberH", dt);

 cmd.CommandTimeout = 0;
 cmd.Connection.Open();
 cmd.ExecuteNonQuery();// Its failing here

My Sp consists of table type param @MemberHType and the procedure returns rows with these columns:

    Name        | Type
    ------------+----------
    Code        | varchar
    Description | varchar
    NodeID      | smallint
    MemberHId   | hierarchyid
    Level       | smallint

This is the procedure:

    alter PROCEDURE [dbo].[InsertHierarchyData]  
    (  
      @MemberHType MemberH READONLY  
    )  
    AS  
    
    truncate table test
    BEGIN TRY   
     
       insert into test values ('start select')
      
     --create table test (errormessage varchar(1000))
    
     IF EXISTS (SELECT TOP 1 1 FROM @MemberHType)  
     BEGIN  
    
     insert into test values ('Inside first Insert start')
      INSERT INTO HierarchyStaging  
      (  
       Code  
       ,[Description]  
       ,NodeID  
       ,MemberhHId  
       ,[Level]  
      )  
      SELECT    
        Code  
        ,[Description]  
        ,NodeId  
        ,MemberhHId  
        ,[Level]  
      FROM @MemberHType  
      insert into test values ('Inside first Insert end')
     END  
     END TRY    
    BEGIN CATCH    
     SELECT   @comment = ERROR_MESSAGE()    
       ,@Status = 'Error'    
     SET   @comment = CONVERT(NVARCHAR(3000),@Comment) + ' Error Severity: ' + CAST(ERROR_SEVERITY() AS varchar(25)) + ' Error state: 30'    
     GOTO ErrorHandler    
    END CATCH    
    The Column in c# is SqlHierarchyId.

Stack-trace:

at System.Data.SqlClient.TdsParser.TdsExecuteRPC(SqlCommand cmd, _SqlRPC[] rpcArray, Int32 timeout, Boolean inSchema, SqlNotificationRequest notificationRequest, TdsParserStateObject stateObj, Boolean isCommandProc, Boolean sync, TaskCompletionSource`1 completion, Int32 startRpc, Int32 startParam)
   at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, Boolean inRetry, SqlDataReader ds, Boolean describeParameterEncryptionRequest)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry)
   at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry)
   at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
Dai
  • 141,631
  • 28
  • 261
  • 374
Rajiv Bansal
  • 45
  • 1
  • 8
  • can you add your sproc? – Ed Bangga Sep 04 '19 at 05:59
  • Azure SQL supports hierarchyid: https://learn.microsoft.com/en-us/sql/t-sql/data-types/hierarchyid-data-type-method-reference?view=sql-server-2017 - are you actually using Azure SQL Data warehouse? – Caius Jard Sep 04 '19 at 06:01
  • Also I understand the need for hiding sensitive info when posting on the internet, but please don't obscure your data to the point that you replace an entire list/array/table of complex types with a simple string of "data" in your sproc's "@table" parameter. Show an actual example object with dummy data – Caius Jard Sep 04 '19 at 06:06
  • This question can not be answered based only on the information it contains. Please try to remember that none of us can read your mind. Create a proper [mcve] if you want your question to be answered. – Zohar Peled Sep 04 '19 at 06:13
  • Ok, will edit it – Rajiv Bansal Sep 04 '19 at 06:59
  • Please let me know if you need any more details, as i am struggling on this issue since 3 days, tried all possible things – Rajiv Bansal Sep 04 '19 at 07:22
  • @ Caius Jard, @Zohar- let me know if you need some more details i can share that as well. – Rajiv Bansal Sep 04 '19 at 07:24

1 Answers1

1

If I understand the documentation correctly, you can't use SqlHierarchyId as the data type of a DataColumn.

It doesn't appear in the System.Data.SqlTypes Namespace, and it also doesn't appear in the SQL Server Data Type Mappings table, which means there's no documented built in conversion between SQL Server's HierarchyId and a built in type in the .Net framework. (of course, undocumented features have been known to exist in SQL Server, but I wouldn't recommend relying on that).

What you can do, however, is to convert the HierarchyId to nvarchar using a simple cast in T-SQL when you read it into your c# application (which internally is calling the ToString() method):

CAST(MemberhHId  AS nvarchar(4000)) as MemberHId

and convert it back using cast when you insert the data (which internally is calling the Parse() method):

CAST(MemberHId AS hierarchyid) 
Zohar Peled
  • 79,642
  • 10
  • 69
  • 121
  • Hey Zohar, SqlHierarchyId is present in Microsoft.SqlServer.Types.dll, and the error is coming while doing the assignment of the sp, i.e. while passing the parameter from C# to the sp. – Rajiv Bansal Sep 04 '19 at 08:57
  • Yes, it's there because it's a CLR type in SQL Server. that doesn't mean it can be used as a type when inserting a table valued parameter using ADO.Net. – Zohar Peled Sep 04 '19 at 08:59
  • If i remove also, the autogenerated DataColumn type is SqlHierarchyId, and the error is same – Rajiv Bansal Sep 04 '19 at 09:09
  • And also when i use the column-type as string its working, why so? and the data which is there would not get corrupted. – Rajiv Bansal Sep 04 '19 at 09:12
  • I'm not sure I understand your last comment. Are you saying that ADO.Net automatically converts SQL Server's HierarchyId to a string and back for you? If that's the case, then it's even simpler then I thought... – Zohar Peled Sep 04 '19 at 09:21
  • Ya, its doing that(ADO.Net automatically converts SQL Server's HierarchyId to a string)....and how do i stop that, as i already said if i take the column type as String, the data flow works seamlessly. – Rajiv Bansal Sep 04 '19 at 09:49
  • Why would you want to stop that? it seems like you're getting what you want, Don't you? – Zohar Peled Sep 04 '19 at 09:55
  • Ya, but its throwing the same exception which i have mentioned. – Rajiv Bansal Sep 04 '19 at 10:02
  • I'm confused. When the data type of the column in the c# data table is `string`, you say ADO.Net automatically convert the `heirarchyId` for you - but you're still getting an error? – Zohar Peled Sep 04 '19 at 10:15
  • No, You are getting me wrong.....so when i don't put the column types c# is converting the column type to SqlHierarchyId. And When i specifically use the Column type as String its working seamlessly – Rajiv Bansal Sep 04 '19 at 10:22
  • Admittedly, English is not my native language, but to the best of my knowledge, "working seamlessly" means everything is working as it should - so if you're setting the data type of the column to a string, you're saying data is transferring correctly from one database to the other. Is that correct? – Zohar Peled Sep 04 '19 at 10:31
  • Yes, That is correct after i set it to string, but here my only concern is data loss would occur if i convert it to string. – Rajiv Bansal Sep 04 '19 at 10:34
  • Well, that can be quite easily tested... Just create a demo application that takes information from one table and inserts it to another table on the same database. Compare both tables content once completed, and then you'll know if you've lost data or not. Personally, if it's something ADO.Net is doing for you, I wouldn't worry too much - but no one is stopping you from testing.... – Zohar Peled Sep 04 '19 at 10:37