2010-10-01 9 views
9

Estoy usando entidad framework 4.FunctionImport in entity framework 4 número

Tengo un procedimiento almacenado que solo actualiza un valor en mi tabla, es decir, el ID del estado de la aplicación. Así que creé un procedimiento almacenado que se ve así:

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

AS 

BEGIN 

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

END 

Creé una función de importación llamada UpdateApplicationState. Inicialmente establecí su tipo de devolución en nulo, pero luego no se creó en el contexto. Entonces cambié su tipo de devolución a int. Ahora fue creado en el contexto. ¿Es prudente devolver algo de mi procedimiento almacenado?

Aquí es mi método en mi clase ApplicationRepository:

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

Aquí está mi código de llamada a este método en mi opinión:

applicationRepository.UpdateApplicationState(id, newApplicationStateID); 

Cuando corro, entonces me sale el siguiente error:

The data reader returned by the store data provider does not have enough columns for the query requested.

¿Alguna idea/consejo sobre lo que puedo hacer para que esto funcione?

Gracias

+0

¿Alguien sabe si esto se resuelve en EF5? –

Respuesta

16

Es debido a que en realidad no devolver nada de su procedimiento almacenado. Agregue una línea como la siguiente a su SP (SELECT @@ ROWCOUNT), y se ejecutará correctamente.

BEGIN  
    ... 

    SELECT @@ROWCOUNT 
END 

Si bien esta solución a tu problema y, de hecho devuelve el número de filas efectuadas por el SP, no me queda claro el por qué esto es un problema para usted:

I had initially set its return type to null, but then it wasn't created in the context.

Al hacer una Función Importar, puede seleccionar "Ninguno" como tipo de devolución y generará un nuevo método en su ObjectContext con un tipo de devolución de int. Este método básicamente ejecuta un procedimiento almacenado que se define en la fuente de datos; descarta cualquier resultado devuelto por la función; y devuelve el número de filas afectadas por la ejecución.

EDIT: ¿Por qué una función sin valor de retorno es ignorado en un escenario POCO:

Perforación en ObjectContext T4 archivo de plantilla viene con ADO.NET C# POCO Entidad Generador revela por qué no puede ver a su Función en su clase ObjectContext: ¡simplemente se ignora! Se escapan a la siguiente iteración en el ciclo foreach que genera las funciones.

La solución para esto es cambiar la plantilla T4 para generar realmente un método para Funciones sin tipo de retorno o simplemente devolver algo basado en la primera solución.

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)); 
    ... 
+0

Cuando selecciono ninguno, la importación de la función no está en el contexto de mi objeto. No existe. Lo busqué. Cuando lo selecciono para que tenga un tipo de devolución, entonces está en el contexto de mi objeto. Estoy usando el generador de entidades POCO. –

+0

No necesito devolver nada, es por eso que quería establecer el tipo de devolución como none, pero cuando lo hago de esta manera, entonces no existe en el contexto de mi objeto. –

+0

Sí, tiene razón, en un escenario POCO, se ignora y edito mi respuesta para mostrar el motivo de este comportamiento. Pensé que estás usando EntityObjects porque no es un problema allí. –

20

Para que POCO funcione con importaciones de funciones que devuelven nulo, puede personalizar el archivo .Context.tt de esta manera.

Busque la región con el nombre "Importaciones de funciones" (la sección que comienza con la región.Begin ("Importaciones de funciones"); y termina con region.End();) en el archivo .Context.tt y reemplazar toda esa sección con lo siguiente:

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(); 

Lo que estoy haciendo aquí es en lugar de ignorar todas las importaciones de funciones que devuelven nula, Estoy creando un método que devuelve nulo. Espero que esto sea útil.

+1

+1 por proporcionar realmente una solución – bernhof

+0

+1 por proporcionar una solución –

Cuestiones relacionadas