使用Entity Framework 4.0 / .edmx从c#调用标量函数

我想将我的标量函数映射到我的.edmx但它失败了。 我右键单击我的entity framework映射,并从数据库中选择更新模型。 它出现在我的模型浏览器中的存储过程文件夹中。

但是,当我想将其添加到模型浏览器中的Function Imports文件夹时,下拉列表中不显示消息标量函数 。 有人能帮我吗?

我可以使用旧方法调用标量函数,例如:

 dbContext.ExecuteStoreQuery( "SELECT dbo.getMinActualLoadDate ({0}, {1}, {2}) AS MyResult", LoadPkid, LoadFkStartLoc, TripSheetPkid).First(); 

但这不是最好的方式。 我的经理希望我找到一种能够将标量函数放在“函数导入”文件夹中的方法,这样我就可以使用以下代码而不是前面的代码来调用标量函数:

 dbContext.ExecuteFunction("getMinActualLoadDate ", paramList); 

我试图添加一个图像来显示我的意思,但由于我的声誉仍然很低,我无法这样做。 然而,图像可以在这里找到: http : //social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/756865e5-ff25-4f5f-aad8-fed9d741c05d

谢谢。

我遇到过同样的问题。 这里是解决方案我发现自己足够合适(在EF5中测试,但也应该在EF4中工作):

不支持将标量值函数映射到开箱即用,但您可以直接执行它们。

您还可以编辑edmx文件以使edmx为标量值函数生成正确的方法,但如果您将模型与数据库同步,则将删除它。

自己编写标量值函数实现:

 string sqlQuery = "SELECT [dbo].[CountMeals] ({0})"; Object[] parameters = { 1 }; int activityCount = db.Database.SqlQuery(sqlQuery, parameters).FirstOrDefault(); 

或者编辑edmx并添加Xml以用于标量值函数的自定义maping:

   SELECT [dbo].[CountActivities] (@personId)    

此信息可在此博客文章中找到

这是我对这个问题的解决方案,这几乎就是你的经理所要求的……尽管已经晚了18个月。

作为一种香草方法:

  ///  /// Calls a given Sql function and returns a singular value ///  /// Current DbContext instance /// CLR Type /// Sql function /// Sql function parameters /// Owning schema /// Value of T public T SqlScalarResult(DbContext db, string sql, SqlParameter[] parameters, string schema = "dbo") { if (string.IsNullOrEmpty(sql)) { throw new ArgumentException("function"); } if (parameters == null || parameters.Length == 0) { throw new ArgumentException("parameters"); } if (string.IsNullOrEmpty(schema)) { throw new ArgumentException("schema"); } string cmdText = $@"SELECT {schema}.{sql}({string.Join(",", parameters.Select(p => "@" + p.ParameterName).ToList())});"; // ReSharper disable once CoVariantArrayConversion return db.Database.SqlQuery(cmdText, parameters).FirstOrDefault(); } } 

并作为EF的扩展方法:

 namespace System.Data.Entity { public static class DatabaseExtensions { ///  /// Calls a given Sql function and returns a singular value ///  /// Current DbContext instance /// CLR Type /// Sql function /// Sql function parameters /// Owning schema /// Value of T public static T SqlScalarResult(this Database db, string sql, SqlParameter[] parameters, string schema = "dbo") { if (string.IsNullOrEmpty(sql)) { throw new ArgumentException("sql"); } if (parameters == null || parameters.Length == 0) { throw new ArgumentException("parameters"); } if (string.IsNullOrEmpty(schema)) { throw new ArgumentException("schema"); } string cmdText = $@"SELECT {schema}.{sql}({string.Join(",", parameters.Select(p => "@" + p.ParameterName).ToList())});"; // ReSharper disable once CoVariantArrayConversion return db.SqlQuery(cmdText, parameters).FirstOrDefault(); } } } 

虽然它不吸烟,但我建议在任何严重使用之前进行unit testing。

我猜你错过了Edit Function Import对话框,您可以在其中生成复杂类型 。 试着探索。

在此处输入图像描述

如果您已成功创建scalars ,则现在可以像这样导航

 using (var con = new DatabaseEntities()) { long? invoiceNo = con.sp_GetInvoiceMaxNumber(code.Length + 2).First(); .... } 

唯一的解决方案是将函数标量类型转换为表值类型,表中有一个值,请参阅代码示例。

您无需更改EDMX XML中的任何内容,请修改SQL函数

标量函数原样,它不起作用

 CREATE FUNCTION [dbo].[GetSha256] ( -- Add the parameters for the function here @str nvarchar(max) ) RETURNS VARBINARY(32) AS BEGIN RETURN ( SELECT * FROM HASHBYTES('SHA2_256', @str) AS HASH256 ); END -- this doesn't work. 

标量函数 – >转换为表值函数,它的工作原理

 CREATE FUNCTION [dbo].[GetSha2561] ( -- Add the parameters for the function here @str nvarchar(max) ) RETURNS @returnList TABLE (CODE varbinary(32)) AS BEGIN INSERT INTO @returnList SELECT HASHBYTES('SHA2_256', @str); RETURN; -- This one works like a charm. END 

Edmx截图

在此处输入图像描述