Проблема отображения скалярной функции в EF core 2.1 - PullRequest
0 голосов
/ 12 февраля 2019

Я пытаюсь отобразить скалярную функцию моей БД, которая имеет собственную схему.Вот как я регистрирую функцию в контексте:

 [DbFunction("ProjectMaterial_GetCostPrice","Project")]
 public static decimal ProjectMaterial_GetCostPrice (int ProjectMaterialID, decimal ExtCost)
 {
    return 0;
 }

Я регистрирую скалярную функцию в частичном классе контекста.А это схема скалярной функции в БД:

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

Ответы [ 2 ]

0 голосов
/ 26 августа 2019

Как описано в предыдущем ответе, вы можете использовать функции, определенные таким образом, только в запросах 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;
}
0 голосов
/ 12 февраля 2019

Используя сам вызов, он генерирует исключение, потому что фактически выполняет код 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 даже через статический вызов не будет работать должным образом, и оно выдает этоисключение (сообщите нам об этом).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...