Я использую 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);
Когда я запускаю его, я получаю следующую ошибку:
В считывателе данных, возвращенном поставщиком данных хранилища, недостаточно столбцов для запрошенного запроса.
Любая идея / совет о том, что я могу сделать, чтобы заставить это работать?
Спасибо
Это потому, что вы на самом деле ничего не возвращаете из хранимой процедуры. Добавьте строку, как показано ниже, к вашему SP ( SELECT @@ ROWCOUNT ), и она будет работать правильно.
BEGIN
...
SELECT @@ROWCOUNT
END
Хотя это решение решит вашу проблему и на самом деле вернет количество затронутых строк вашим SP, я не понимаю, почему это проблема для вас:
Сначала я установил тип возвращаемого значения на ноль, но затем он не был создан в контексте.
При выполнении импорта функций вы можете выбрать «Нет» в качестве возвращаемого типа, и он сгенерирует новый метод в вашем 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));
...
Чтобы заставить 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();
То, что я делаю здесь, вместо того, чтобы игнорировать все импорты функций, которые возвращают ноль, я создаю метод, который возвращает нуль. Я надеюсь, что это полезно.