Подтвердить что ты не робот

Вызов скалярной функции из С# с использованием Entity Framework 4.0/.edmx

Я хотел бы сопоставить свою скалярную функцию с моим .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

Спасибо.

4b9b3361

Ответ 1

Я столкнулся с той же проблемой. И вот решение, которое я нашел достаточно подходящим для себя (тестировался в 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>

Эта информация была найдена в этом сообщении

Ответ 2

Вот мое решение этой проблемы, и это почти то, о чем просил ваш менеджер.. хотя и опоздал на 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(sql)) {
            throw new ArgumentException("schema");
        }

        string cmdText =
            [email protected]"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 =
                [email protected]"SELECT {schema}.{sql}({string.Join(",", 
                    parameters.Select(p => "@" + p.ParameterName).ToList())});";

            // ReSharper disable once CoVariantArrayConversion
            return db.SqlQuery<T>(cmdText, parameters).FirstOrDefault();

        }

    }

}

Хотя он не курит здесь, я предлагаю тестировать устройство перед серьезным использованием.

Ответ 3

Я думаю, вы пропустите диалог Edit Function Import, где вы можете создавать сложные типы. попытайтесь исследовать.

enter image description here

Если вы успешно создали scalars, теперь вы можете перемещаться таким образом

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

Ответ 4

Единственное решение - преобразовать тип скалярного типа в тип значения таблицы с единственным значением в таблице, см. пример кода.

Вам не нужно ничего менять в 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

введите описание изображения здесь