jay*_*jay 21 c# user-defined-functions entity-framework-4
我想将我的标量函数映射到我的.edmx但它失败了.我右键单击我的实体框架映射,并从数据库中选择更新模型.它出现在我的模型浏览器中的存储过程文件夹中.
但是,当我想将它添加到Function Imports模型浏览器中的我的文件夹时,消息标量函数不会出现在下拉列表中.有人能帮我吗?
我可以使用旧方法调用标量函数,例如:
dbContext.ExecuteStoreQuery<DateTime?>(
"SELECT dbo.getMinActualLoadDate ({0}, {1}, {2}) AS MyResult",
LoadPkid, LoadFkStartLoc, TripSheetPkid).First();
Run Code Online (Sandbox Code Playgroud)
但这不是最好的方法.我的经理希望我找到一种能够将标量函数放在"函数导入"文件夹中的方法,这样我就可以使用以下代码而不是前面的代码来调用标量函数:
dbContext.ExecuteFunction("getMinActualLoadDate ", paramList);
Run Code Online (Sandbox Code Playgroud)
我试图添加一个图像来显示我的意思,但由于我的声誉仍然很低,我无法这样做.然而,图像可以在这里找到:http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/756865e5-ff25-4f5f-aad8-fed9d741c05d
谢谢.
Pav*_*kiy 14
我遇到过同样的问题.这里是解决方案我发现自己足够合适(在EF5中测试,但也应该在EF4中工作):
不支持将标量值函数映射到开箱即用,但您可以直接执行它们.
您还可以编辑edmx文件以使edmx为标量值函数生成正确的方法,但如果您将模型与数据库同步,则将删除它.
自己编写标量值函数实现:
string sqlQuery = "SELECT [dbo].[CountMeals] ({0})";
Object[] parameters = { 1 };
int activityCount = db.Database.SqlQuery<int>(sqlQuery, parameters).FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)
或编辑edmx并添加Xml以用于标量值函数的自定义maping:
<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>
Run Code Online (Sandbox Code Playgroud)
此信息可在此博客文章中找到
以下是我对这个问题的解决方案,这几乎就是你的经理所要求的......尽管已经晚了18个月.
作为一种香草方法:
/// <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();
}
}
Run Code Online (Sandbox Code Playgroud)
并作为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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
虽然它不吸烟,但我建议在严重使用之前进行单元测试.
我猜您错过了Edit Function Import可以生成复杂类型的对话框。尝试探索。

如果您已成功创建scalars,您现在可以像这样导航
using (var con = new DatabaseEntities())
{
long? invoiceNo = con.sp_GetInvoiceMaxNumber(code.Length + 2).First();
....
}
Run Code Online (Sandbox Code Playgroud)