24

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

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

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

dbContext.ExecuteStoreQuery<DateTime?>(
"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

谢谢。

4

5 回答 5

17

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

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

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

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

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

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

<Function Name="CountActivities" Aggregate="false" BuiltIn="false"    NiladicFunction="false" IsComposable="false"   ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo">
    <CommandText>
        SELECT [dbo].[CountActivities] (@personId)
    </CommandText>
    <Parameter Name="personId" Type="int" Mode="In" />
</Function>

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

于 2013-10-29T09:17:07.220 回答
8

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

作为香草方法:

    /// <summary>
    /// Calls a given Sql function and returns a singular value
    /// </summary>
    /// <param name="db">Current DbContext instance</param>
    /// <typeparam name="T">CLR Type</typeparam>
    /// <param name="sql">Sql function</param>
    /// <param name="parameters">Sql function parameters</param>
    /// <param name="schema">Owning schema</param>
    /// <returns>Value of T</returns>
    public T SqlScalarResult<T>(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<T>(cmdText, parameters).FirstOrDefault();

    }

}

作为 EF 的扩展方法:

namespace System.Data.Entity {

    public static class DatabaseExtensions {

        /// <summary>
        /// Calls a given Sql function and returns a singular value
        /// </summary>
        /// <param name="db">Current DbContext instance</param>
        /// <typeparam name="T">CLR Type</typeparam>
        /// <param name="sql">Sql function</param>
        /// <param name="parameters">Sql function parameters</param>
        /// <param name="schema">Owning schema</param>
        /// <returns>Value of T</returns>
        public static T SqlScalarResult<T>(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<T>(cmdText, parameters).FirstOrDefault();

        }

    }

}

虽然这里不冒烟,但我建议在认真使用之前进行单元测试。

于 2014-08-20T06:58:08.490 回答
1

我猜你错过了Edit Function Import可以生成Complex Types的对话框。尝试探索。

在此处输入图像描述

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

using (var con = new DatabaseEntities())
{
   long? invoiceNo = con.sp_GetInvoiceMaxNumber(code.Length + 2).First();
   ....
}
于 2013-01-23T23:54:33.850 回答
1

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

您不必更改 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 截图

在此处输入图像描述

于 2017-08-17T05:31:31.657 回答
0

页面代码:

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        using (MayEntities context = new MayEntities())
        {
            string str = context.Database.SqlQuery<string>("select dbo.HeyYou()").Single().ToString();
            Response.Write(str); //output:'Hey this works'
        }
    }
}

标量函数:

CREATE FUNCTION [dbo].[HeyYou] ()
RETURNS varchar(20)
AS
BEGIN
    RETURN 'Hey this works'
END
go
于 2019-08-02T11:36:55.730 回答