从 Linq Query 调用 SQL 标量函数

Posted

技术标签:

【中文标题】从 Linq Query 调用 SQL 标量函数【英文标题】:Calling SQL scalar function from Linq Query 【发布时间】:2016-03-12 21:39:05 【问题描述】:

这里有很多类似的线程,但是没有一个解决不了我的问题。

据我所知,从 linq 调用 SQL 标量函数有两种方法。

1。方法:

我已使用 XML 编辑器将我的函数添加到 .edmx 文件中,我的函数是:

<Function Name="prisustvoPostotci" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="false" ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo">
  <CommandText>
    select dbo.prisustvoPostotci(@matica_ID,@godina)
  </CommandText>
  <Parameter Name="matica_ID" Type="int" Mode="In" />
  <Parameter Name="godina" Type="int" Mode="In" />
</Function>

我进入模型浏览器并在Function Imports中双击我的函数并将返回集合类型更改为Int32。我的函数返回整数。

现在我可以使用以下方法从 linq 调用我的函数:

using (DB_Entities dm = new DB_Entities())

  dm.prisustvoPostotci(1, 2016).FirstOrDefault();

它返回有效的整数值!

但是如果我像这样从 Linq Query 调用我的函数:

query = query.Where(x => x.date.Value.Year == max_year &&
                dm.prisustvoPostotci(x.ID, max_year).FirstOrDefault() >= 50);

它会抛出这个错误:

LINQ to Entities 无法识别该方法 'System.Data.Entity.Core.Objects.ObjectResult1[System.Nullable1[System.Int32]] prisustvoPostotci(System.Nullable1[System.Int32], System.Nullable1[System.Int32])' 方法,而这个方法不能 翻译成商店表达式。

2。方法:

我已使用 XML 编辑器将我的函数添加到 .edmx 文件中,我的函数是:

<Function Name="prisustvoPostotci" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="false" ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo">
  <CommandText>
    select dbo.prisustvoPostotci(@matica_ID,@godina)
  </CommandText>
  <Parameter Name="matica_ID" Type="int" Mode="In" />
  <Parameter Name="godina" Type="int" Mode="In" />
</Function>

我进入模型浏览器并在Function Imports中双击我的函数并将返回集合类型更改为Int32。我的函数返回整数。

然后我创建了一个分部类并写了这个方法:

public static class EntityFunctions

    [EdmFunction("Model.Store", "prisustvoPostotci")] 
    public static int prisustvoPostotci(int matica_ID, int godina) 
    
        throw new NotSupportedException("Direct calls not supported"); 
     


“Model.Store”是从 .edmx 文件中的架构命名空间中读取的模型存储的正确名称。

现在,如果我使用 linq 从 linq 调用我的函数:

EntityFunctions.prisustvoPostotci(119, 2016).ToString()

它会抛出这个错误:

throw new NotSupportedException("不支持直接调用");

另外,如果我像这样从 Linq Query 调用我的函数:

query = query.Where(x => x.date.Value.Year == max_year &&
                EntityFunctions.prisustvoPostotci(x.ID, max_year) >= 50);

它会抛出这个错误:

函数或函数 import 'Model.Store.prisustvoPostotci' 不可组合。不能在查询表达式中调用不可组合的函数或函数导入。

我试图编辑我的 .edmx 文件并更改属性 IsComposable="true",但它给了我这个错误:

声明命令文本的函数不能组合。

你能帮我解决这个问题吗!? 非常感谢提前!!

::欢呼声::

乔斯普

【问题讨论】:

你应该定义一个返回类型:programmaticponderings.wordpress.com/2012/11/22/… 如果您打算将 ReturnType="int" 或 ReturnType="Int32" 添加到我的 .edmx 文件中,则会返回此错误:“无法组合的函数不得声明返回类型。” ?? 您正在尝试将标量函数用作可组合函数(即可在查询中使用,例如在您的 Where 子句中)。这只支持表值函数。 我对表函数不熟悉。是否可以实现表函数而不是标量函数以返回整数值? 【参考方案1】:

感谢 Gerd Arnold,我意识到标量函数不能在查询 where 语句中使用。

这是我通过在查询之外调用标量函数来过滤查询的方法:

var result = query.ToList();

for (int i = 0; i < result.Count; i++)

    // prisustvoPostotci(ID, year) is my scalar function
    if (dm.prisustvoPostotci(result[i].ID, max_year).FirstOrDefault() >= 50)
    
        result.Remove(result[i]);
        i--;
    
   

这样调用标量函数就可以了,我们可以从结果中删除匹配的记录!

希望这会对某人有所帮助。

:: 干杯 ::

乔斯普

【讨论】:

以上是关于从 Linq Query 调用 SQL 标量函数的主要内容,如果未能解决你的问题,请参考以下文章

在LINQ to Entities查询中调用自定义标量数据库函数?

使用 EXECUTE 从 SQL Server 调用用户定义函数时的标量结果不同

SQL Server如何定位自定义标量函数被那个SQL调用次数最多浅析

sql 标量函数

嗨,我是sql初学者。我在(UDF)函数标量中有问题

用东西 sql 修剪标量 UDF