FunctionImport dans le cadre de l'entité numéro 4

entity entity-framework

Question

J'utilise le framework d'entité 4.

J'ai une procédure stockée qui ne met à jour qu'une valeur dans ma table, à savoir l'ID d'état de l'application. J'ai donc créé une procédure stockée qui ressemble à ceci:

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

AS

BEGIN

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

END

J'ai créé une fonction d'importation appelée UpdateApplicationState. J'avais initialement défini son type de retour sur null, mais il n'était pas créé dans le contexte. J'ai donc changé son type de retour en int. Maintenant, il a été créé dans le contexte. Est-il sage de renvoyer quelque chose de ma procédure stockée?

Voici ma méthode dans ma classe ApplicationRepository:

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

Voici mon code d'appel à cette méthode à mon avis:

applicationRepository.UpdateApplicationState(id, newApplicationStateID);

Quand je le lance, j'obtiens l'erreur suivante:

Le lecteur de données renvoyé par le fournisseur de données de magasin n'a pas assez de colonnes pour la requête demandée.

Toute idée / conseil sur ce que je peux faire pour que cela fonctionne?

Merci

Réponse acceptée

C'est parce que vous ne renvoyez rien dans votre procédure stockée. Ajoutez une ligne similaire à celle ci-dessous à votre SP ( SELECT @@ ROWCOUNT ), et il s'exécutera correctement.

BEGIN    
    ...

    SELECT @@ROWCOUNT
END

Bien que cette solution résolve votre problème et renvoie réellement le nombre de lignes effectuées par votre fournisseur de service, je ne comprends pas pourquoi c'est un problème pour vous:

J'avais initialement défini son type de retour sur null, mais il n'était pas créé dans le contexte.

Lorsque vous effectuez une importation de fonction, vous pouvez sélectionner "Aucun" comme type de retour. Une nouvelle méthode sera alors générée sur votre ObjectContext avec un type de retour de type int . Cette méthode exécute essentiellement une procédure stockée définie dans la source de données. ignore tous les résultats renvoyés par la fonction; et renvoie le nombre de lignes affectées par l'exécution.

EDIT: Pourquoi une fonction sans valeur de retour est ignorée dans un scénario POCO:

L' exploration du fichier modèle ObjectContext T4 fourni avec ADO.NET C # POCO Entity Generator révèle pourquoi vous ne pouvez pas voir votre fonction dans votre classe ObjectContext: c'est simplement ignoré! Ils échappent à la prochaine itération dans la boucle foreach qui génère les fonctions.

La solution de contournement consiste à modifier le modèle T4 afin de générer une méthode pour les fonctions sans type de retour ou à renvoyer simplement un élément basé sur la première solution.

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

Réponse populaire

Pour que POCO fonctionne avec les importations de fonctions qui renvoient null, vous pouvez personnaliser le fichier .Context.tt comme ceci.

Recherchez la région nommée "Function Imports" (la section commençant par region.Begin ("Importations de fonction"); et se terminant par region.End ();) dans le fichier .Context.tt et remplacez toute cette section par ce qui suit:

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

Au lieu d'ignorer toutes les importations de fonctions renvoyant la valeur null, je crée une méthode qui renvoie la valeur null. J'espère que ceci est utile.



Related

Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow