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.
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
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.
je suppose que vous manquez l' Edit Function Import
boîte de dialogue où vous pouvez générer Types Complexes. essayez d'explorer.
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();
....
}
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