FunctionImport в рамках сущности 4 выпуска - PullRequest
9 голосов
/ 01 октября 2010

Я использую Entity Framework 4.

У меня есть хранимая процедура, которая просто обновляет одно значение в моей таблице, а именно идентификатор состояния приложения.Поэтому я создал хранимую процедуру, которая выглядит следующим образом:

ALTER PROCEDURE [dbo].[UpdateApplicationState]
(
   @ApplicationID INT,
   @ApplicationStateID INT
)

AS

BEGIN

   UPDATE
      [Application]
   SET
      ApplicationStateID = @ApplicationStateID
   WHERE
      ApplicationID = @ApplicationID;

END

Я создал функцию импорта с именем UpdateApplicationState.Сначала я установил тип возвращаемого значения на ноль, но потом он не был создан в контексте.Поэтому я изменил тип возвращаемого значения на int.Теперь это было создано в контексте.Разумно ли возвращать что-то из моей хранимой процедуры?

Вот мой метод в моем классе ApplicationRepository:

public void UpdateApplicationState(int applicationID, int applicationStateID)
{
   var result = context.UpdateApplicationState(applicationID, applicationStateID);
}

Вот мой код вызова этого метода, на мой взгляд:

applicationRepository.UpdateApplicationState(id, newApplicationStateID);

Когда я его запускаю, я получаю следующую ошибку:

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

Любая идея / совет о том, что я могу сделать, чтобы заставить это работать?

Спасибо

Ответы [ 2 ]

20 голосов
/ 26 ноября 2010

Чтобы заставить POCO работать с импортом функций, которые возвращают ноль, вы можете настроить файл .Context.tt следующим образом.

Найдите именованную область «Импорт функций» (раздел, начинающийся с region.Begin(«Импорт функций»); заканчивается на region.End ();) в файле .Context.tt и заменяет весь этот раздел следующим текстом:

    region.Begin("Function Imports");

        foreach (EdmFunction edmFunction in container.FunctionImports)
        {
            var parameters = FunctionImportParameter.Create(edmFunction.Parameters, code, ef);
            string paramList = String.Join(", ", parameters.Select(p => p.FunctionParameterType + " " + p.FunctionParameterName).ToArray());
            var isReturnTypeVoid = edmFunction.ReturnParameter == null;
            string returnTypeElement = String.Empty;
            if (!isReturnTypeVoid) 
                returnTypeElement = code.Escape(ef.GetElementType(edmFunction.ReturnParameter.TypeUsage));

#>
<# if (isReturnTypeVoid) { #>
    <#=Accessibility.ForMethod(edmFunction)#> void <#=code.Escape(edmFunction)#>(<#=paramList#>)    
<# } else { #>
    <#=Accessibility.ForMethod(edmFunction)#> ObjectResult<<#=returnTypeElement#>> <#=code.Escape(edmFunction)#>(<#=paramList#>)    
<# } #>
    {
<#
            foreach (var parameter in parameters)
            {
                if (!parameter.NeedsLocalVariable)
                {
                    continue;
                }
#>

        ObjectParameter <#=parameter.LocalVariableName#>;

        if (<#=parameter.IsNullableOfT ? parameter.FunctionParameterName + ".HasValue" : parameter.FunctionParameterName + " != null"#>)
        {
            <#=parameter.LocalVariableName#> = new ObjectParameter("<#=parameter.EsqlParameterName#>", <#=parameter.FunctionParameterName#>);
        }
        else
        {
            <#=parameter.LocalVariableName#> = new ObjectParameter("<#=parameter.EsqlParameterName#>", typeof(<#=parameter.RawClrTypeName#>));
        }
<#
            }
#>
<# if (isReturnTypeVoid) { #>
        base.ExecuteFunction("<#=edmFunction.Name#>"<#=code.StringBefore(", ", String.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray()))#>);
<# } else { #>
        return base.ExecuteFunction<<#=returnTypeElement#>>("<#=edmFunction.Name#>"<#=code.StringBefore(", ", String.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray()))#>);
<# } #>

    }
<#
        }

        region.End();

Вместо этого я делаю здесьигнорируя все функции импорта, которые возвращают ноль, я создаю метод, который возвращает ноль.Я надеюсь, что это полезно.

16 голосов
/ 02 октября 2010

Это потому, что вы на самом деле ничего не возвращаете из своей хранимой процедуры.Добавьте строку, подобную приведенной ниже, к вашему SP ( SELECT @@ ROWCOUNT ), и она будет работать правильно.

BEGIN    
    ...

    SELECT @@ROWCOUNT
END

Хотя это решение решит вашу проблему и фактически вернет числозатронул ряды вашим SP, мне не ясно, почему это проблема для вас:

Я изначально установил тип возвращаемого значения на ноль, но затем он не был создан вcontext.

При выполнении импорта функций вы можете выбрать "None" в качестве типа возврата, и он создаст новый метод в вашем ObjectContext с типом возврата: INT .Этот метод в основном выполняет хранимую процедуру, которая определена в источнике данных;отбрасывает любые результаты, возвращаемые функцией;и возвращает количество строк, затронутых выполнением.

РЕДАКТИРОВАТЬ: Почему функция без возвращаемого значения игнорируется в сценарии POCO:

Детализация в шаблон ObjectContext T4 файл поставляется с ADO.NET C # POCO Entity Generator показывает, почему вы не видите свою функцию в своем классе ObjectContext: просто она игнорируется!Они переходят к следующей итерации в цикле foreach, который генерирует функции.

Обходной путь для этого состоит в том, чтобы изменить шаблон T4, чтобы фактически генерировать метод для функций без типа возврата или просто возвращать что-то на основе первого решения.

region.Begin("Function Imports");

foreach (EdmFunction edmFunction in container.FunctionImports)
{
    var parameters = FunctionImportParameter.Create(edmFunction.Parameters, code, ef);
    string paramList = String.Join(", ", parameters.Select(p => p.FunctionParameterType + " " + p.FunctionParameterName).ToArray());

    // Here is why a Function without return value is ignored:
    if (edmFunction.ReturnParameter == null)
    {
        continue;
    }
    string returnTypeElement = code.Escape(ef.GetElementType(edmFunction.ReturnParameter.TypeUsage));
    ...
...