我正在尝试映射具有自定义模式的数据库的标量函数。这就是我在上下文中注册函数的方式:
[DbFunction("ProjectMaterial_GetCostPrice","Project")]
public static decimal ProjectMaterial_GetCostPrice (int ProjectMaterialID, decimal ExtCost)
{
return 0;
}
我正在上下文的部分类中注册Scalar函数。这是数据库中标量函数的架构:
-- Select Project.ProjectDriver_GetCostPrice (5456921)
ALTER FUNCTION [Project].[ProjectMaterial_GetCostPrice] (@ProjectMaterialID int, @ExtCost money)
RETURNS MONEY
AS
我还根据文档建议更改了方法的正文:
throw new NotSupportedException();
它引发了异常,而不是调用了函数
这就是我调用该函数的方式:
var newCostPrice= NsiteDBContext.ProjectMaterial_GetCostPrice(projectMaterial.ProjectMaterialId, projectMaterial.CostPrice.Value);
答案 0 :(得分:1)
使用调用本身会引发异常,因为它实际上执行C#代码。建议抛出异常的原因正是这样,以避免意外使用,即通过直接调用它。该签名将由给定的LINQ提供程序解释并转换为适当的SQL语句。
为此,EF上下文需要知道如何使用,因此可能是某种方式
var items = await ctx.Materials.Select(c = > new {
Material= c,
CostPrice = ProjectMaterial_GetCostPrice(c.ProjectMaterialId, c.CostPrice.Value),
}).ToListAsync();
现在ctx
对象在解析表达式树时将知道如何转换ProjectMaterial_GetCostPrice
签名。
即使通过静态调用,在select语句之外执行操作也无法按预期进行,并且会抛出该异常(通知我们)。
答案 1 :(得分:0)
如上一个答案所述,您只能在LINQ查询中使用以这种方式定义的函数。 若要直接调用SQL标量值函数,应使用DbContext.Database.ExecuteSqlCommand方法对其进行定义。这样,它应该可以工作:
public decimal ProjectMaterial_GetCostPrice(int ProjectMaterialID, decimal ExtCost)
{
System.Data.SqlClient.SqlParameter resultParam =
new System.Data.SqlClient.SqlParameter
{
ParameterName = "@resultCost",
SqlDbType = System.Data.SqlDbType.Money,
Direction = System.Data.ParameterDirection.Output
};
System.Data.SqlClient.SqlParameter parMaterialID =
new System.Data.SqlClient.SqlParameter("@MaterialID", ProjectMaterialID);
SqlParameter parExtCost =
new System.Data.SqlClient.SqlParameter("@ExtCost", ExtCost);
Database.ExecuteSqlCommand(
"select @resultCost = [Project].[ProjectMaterial_GetCostPrice](@MaterialID, @ExtCost);",
resultParam, parMaterialID, parExtCost);
return (decimal)resultParam.Value;
}