使用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截图