Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call stored procedure from EntityFramework 6 with 'hierarchyid' parameter

Tags:

I am developing a service using WebApi2 and EntityFramework6. I have a legacy SQLServer DB that my service must work with.

That DB is using heavily the 'hierarchyid' data type and this type is used internally in DB's stored procedures.

Seems like EF6 is not supporting 'hierarchyid' data type, so i used this fork that adds support for 'hierarchyid'.

While the retrieval from the DB is working great with the 'hierarchyid' type, my problem is with the Stored Procedures that need a 'hierarchyid' as a parameter.

The stored procedure looks like this:

CREATE PROCEDURE [dbo].[GetSomethingByNodeId]
    (
        @startingRoot HIERARCHYID
        ,@return HIERARCHYID OUTPUT
    )

My client code for invoking this stored procedure looks like this:

var param1 = new SqlParameter("@startingRoot", new HierarchyId("/"));
var param2 = new SqlParameter{ ParameterName = "@return", Value = 0, Direction = ParameterDirection.Output };

var obj = context.Database.SqlQuery<HierarchyId>("GetSomethingByNodeId" @startingRoot, @return out", param1, param2).ToList();

But unfortunately calling this query throws an exception that says:

An unhandled exception of type 'System.ArgumentException' occurred in EntityFramework.SqlServer.dll

Additional information: No mapping exists from object type System.Data.Entity.Hierarchy.HierarchyId to a known managed provider native type.

Any ideas on how i can make this work?

like image 462
Shonn Lyga Avatar asked Aug 12 '16 10:08

Shonn Lyga


People also ask

Does Entity Framework 6 allow calling stored procedure?

The short answer is: "In EF6 -- which works everywhere -- the answer is Yes." As I discuss in my article on Entity Framework 6, you can even tell EF to use your stored procedures to handle updates, deletes and inserts triggered when you call your DbContext object SaveChanges method. And that's cool.

Does Entity Framework allow calling stored procedure?

The Entity Framework has the capability of importing a Stored Procedure as a function. We can also map the result of the function back to any entity type or complex type.

What is Return_value stored procedure?

Return Value in SQL Server Stored Procedure In default, when we execute a stored procedure in SQL Server, it returns an integer value and this value indicates the execution status of the stored procedure. The 0 value indicates, the procedure is completed successfully and the non-zero values indicate an error.


1 Answers

Unfortunately, MetaType.GetMetaTypeFromValue does not allow to add types (all supported types are hardcoded). I think you can accomplish your goal with nvarchar parameters and conversions.

In your C# code:

var param1 = new SqlParameter("@startingRoot", "/1/");
var param2 = new SqlParameter { ParameterName = "@return", Value = "", Size = 1000, Direction = ParameterDirection.Output };

var ids = context.Database.SqlQuery<HierarchyId>("GetSomethingByNodeId @startingRoot, @return out", param1, param2).ToList();
var returnedId = new HierarchyId(param2.Value.ToString());

In your procedure (I wrote some test code inside):

CREATE PROCEDURE [dbo].[GetSomethingByNodeId]
    (
        @startingRoot nvarchar(max), @return nvarchar(max) OUTPUT
    )
as 
declare @hid hierarchyid = hierarchyid::Parse('/1/')
select @return = @hid.ToString()

declare @root hierarchyid = hierarchyid::Parse(@startingRoot)
select @root as field

Also, you can try to use Microsoft.SqlServer.Types and SqlHierarchyId type like this:

var sqlHierarchyId = SqlHierarchyId.Parse("/");
var param1 = new SqlParameter("@startingRoot", sqlHierarchyId) { UdtTypeName = "HierarchyId" };

But, I think, this is wrong direction.

like image 106
OlegAxenow Avatar answered Sep 23 '22 16:09

OlegAxenow