Appeler la fonction scalar à partir de c# en utilisant Entity Framework 4.0/.edmx

j'aimerais carte ma fonction scalaire à mon .edmx mais ça échoue. Je clique avec le bouton droit de la souris sur le mappage de mon framework entity, et je choisis update model à partir de la base de données. Il apparaît dans mon dossier procédures stockées dans mon navigateur model.

Cependant, lorsque je veux ajouter à mon Function Imports dossier dans le navigateur du modèle, le message la fonction scalaire n'apparaît pas affiche dans la liste déroulante. Quelqu'un peut-il m'aider?

je peux appeler la fonction scalaire en utilisant l'ancienne, tels comme:

dbContext.ExecuteStoreQuery<DateTime?>(
"SELECT dbo.getMinActualLoadDate ({0}, {1}, {2}) AS MyResult", 
LoadPkid, LoadFkStartLoc, TripSheetPkid).First();

mais ce n'est pas la meilleure façon. Mon gestionnaire voudrait que je trouve un moyen de mettre la fonction scalar dans le dossier "importation de fonction" pour que je puisse appeler la fonction scalar en utilisant le code suivant au lieu du code précédent:

dbContext.ExecuteFunction("getMinActualLoadDate ", paramList);

j'ai essayé d'ajouter une image à afficher ce que je veux dire, mais comme ma réputation est encore faible, je suis incapable de le faire. Cependant l'image peut être trouvée ici: http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/756865e5-ff25-4f5f-aad8-fed9d741c05d

Merci.

18
demandé sur slavoo 2013-01-17 01:49:04

4 réponses

j'ai rencontré le même problème. Et voici la solution que j'ai trouvé moi-même assez convenable (testé dans EF5, mais devrait aussi fonctionner dans EF4):

il n'y a pas de support de mappage des fonctions de valeur scalaire hors de la boîte mais vous pouvez les exécuter directement.

vous pouvez également éditer le fichier edmx pour faire générer la méthode appropriée pour la fonction de valeur scalaire, mais il sera supprimé si vous synchronisez votre modèle avec la base de données.

Écrire fonction scalaire la mise en œuvre vous-même:

string sqlQuery = "SELECT [dbo].[CountMeals] ({0})";
Object[] parameters = { 1 };
int activityCount = db.Database.SqlQuery<int>(sqlQuery, parameters).FirstOrDefault();

ou éditer edmx et ajouter Xml pour le mappage personnalisé de la fonction de valeur scalaire:

<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>

Cette information a été trouvée dans ce blog

12
répondu Pavel Luzhetskiy 2013-12-08 15:30:43

Voici ma solution à ce problème, qui est presque exactement ce que votre gestionnaire est de demander.. mais 18 mois de retard.

Comme la vanille méthode:

    /// <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(schema)) {
            throw new ArgumentException("schema");
        }

        string cmdText =
            $@"SELECT {schema}.{sql}({string.Join(",",
                parameters.Select(p => "@" + p.ParameterName).ToList())});";

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

    }

}

et comme méthode d'extension à 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 =
                $@"SELECT {schema}.{sql}({string.Join(",", 
                    parameters.Select(p => "@" + p.ParameterName).ToList())});";

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

        }

    }

}

bien qu'il ne fume pas ici, je suggère des tests unitaires avant toute utilisation sérieuse.

6
répondu dperish 2018-10-06 02:41:09

je suppose que vous manquez l' Edit Function Import boîte de dialogue où vous pouvez générer Types Complexes. essayez d'explorer.

enter image description here

Si vous avez créé avec succès le scalars, vous pouvez maintenant naviguer comme ceci

using (var con = new DatabaseEntities())
{
   long? invoiceNo = con.sp_GetInvoiceMaxNumber(code.Length + 2).First();
   ....
}
1
répondu spajce 2013-01-24 00:00:11

la seule et unique solution est de convertir la fonction type scalaire en valeur de table type avec une seule valeur dans la table, s'il vous plaît voir l'échantillon de code.

vous n'avez pas à changer quoi que ce soit dans le XML EDMX, s'il vous plaît modifier la fonction SQL

fonction scalaire telle quelle, qui ne fonctionne pas

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.

fonction scalaire - > converti en fonction de valeur de tableau, il fonctionne

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 capture d'écran

enter image description here

1
répondu Md. Alim Ul Karim 2017-08-17 05:31:31