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?
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With