【问题标题】:Convert VB CLR function to C#将 VB CLR 函数转换为 C#
【发布时间】:2021-07-11 01:16:22
【问题描述】:

如何将 VB.net SQL CLR 函数转换为 VS SSDT SQL 项目的 C# CLR 函数?

我需要将其转换为 C#,因为看起来 built-in SSDT Project support for CLR functions is C# only?如果我能找到一种以与 VS SSDT 项目兼容的方式使用原始 VB 并且不会破坏发布工作流程的方法,那么我会接受这个答案!我发现使用 SSMS 中的 T-SQL 命令将 .dll 编译到 SQL Server 中非常容易……但是当我将它带入我们的 SSDT 项目以合并到我们的下一个 .dacpac 版本中时,没有任何效果!

SqlFunction(IsDeterministic:=True, IsPrecise:=True)> _
Public Shared Function RegExOptionEnumeration(ByVal IgnoreCase As SqlBoolean, _
             ByVal MultiLine As SqlBoolean, _
                           ByVal ExplicitCapture As SqlBoolean, _
                           ByVal Compiled As SqlBoolean, _
                           ByVal SingleLine As SqlBoolean, _
                           ByVal IgnorePatternWhitespace As SqlBoolean, _
                           ByVal RightToLeft As SqlBoolean, _
                           ByVal ECMAScript As SqlBoolean, _
                           ByVal CultureInvariant As SqlBoolean) _
              As SqlInt32
  Dim Result As Integer
  Result = (IIf(IgnoreCase.Value, RegexOptions.IgnoreCase, RegexOptions.None) Or _
   IIf(MultiLine.Value, RegexOptions.Multiline, RegexOptions.None) Or _
   IIf(ExplicitCapture.Value, RegexOptions.ExplicitCapture, _
                RegexOptions.None) Or _
   IIf(Compiled.Value, RegexOptions.Compiled, RegexOptions.None) Or _
   IIf(SingleLine.Value, RegexOptions.Singleline, RegexOptions.None) Or _
   IIf(IgnorePatternWhitespace.Value, RegexOptions.IgnorePatternWhitespace, _
                RegexOptions.None) Or _
   IIf(RightToLeft.Value, RegexOptions.RightToLeft, RegexOptions.None) Or _
   IIf(ECMAScript.Value, RegexOptions.ECMAScript, RegexOptions.None) Or _
   IIf(CultureInvariant.Value, RegexOptions.CultureInvariant, RegexOptions.None))
  Return (Result)

我已尝试通过Telerik C# Converter 运行Class

Telerik 在 C# 下生成:

public class RegularExpressionFunctions
    {
        // 
        // RegExOptions function
        // this is used simply to create the bitmap that is passed to the various 
        // CLR routines

        [SqlFunction(IsDeterministic = true, IsPrecise = true)]
        public static SqlInt32 RegExOptionEnumeration(SqlBoolean IgnoreCase, SqlBoolean MultiLine, SqlBoolean ExplicitCapture, SqlBoolean Compiled, SqlBoolean SingleLine, SqlBoolean IgnorePatternWhitespace, SqlBoolean RightToLeft, SqlBoolean ECMAScript, SqlBoolean CultureInvariant)
        {
            int Result;
            Result = (Interaction.IIf(IgnoreCase.Value, RegexOptions.IgnoreCase, RegexOptions.None) | Interaction.IIf(MultiLine.Value, RegexOptions.Multiline, RegexOptions.None) | Interaction.IIf(ExplicitCapture.Value, RegexOptions.ExplicitCapture, RegexOptions.None) | Interaction.IIf(Compiled.Value, RegexOptions.Compiled, RegexOptions.None) | Interaction.IIf(SingleLine.Value, RegexOptions.Singleline, RegexOptions.None) | Interaction.IIf(IgnorePatternWhitespace.Value, RegexOptions.IgnorePatternWhitespace, RegexOptions.None) | Interaction.IIf(RightToLeft.Value, RegexOptions.RightToLeft, RegexOptions.None) | Interaction.IIf(ECMAScript.Value, RegexOptions.ECMAScript, RegexOptions.None) | Interaction.IIf(CultureInvariant.Value, RegexOptions.CultureInvariant, RegexOptions.None));
            return (Result);
        }
}

类中的所有其他函数似乎都可以使用 Telerik 转换器进行转换。 我试着四处寻找这个,似乎是IIf is similar to ternary operators。在此基础上,我尝试了以下2个示例,但没有任何效果...

尝试 1

[SqlFunction(IsDeterministic = true, IsPrecise = true)]
    public static SqlInt32 RegExOptionEnumeration(SqlBoolean IgnoreCase, SqlBoolean MultiLine, SqlBoolean ExplicitCapture, SqlBoolean Compiled, SqlBoolean SingleLine, SqlBoolean IgnorePatternWhitespace, SqlBoolean RightToLeft, SqlBoolean ECMAScript, SqlBoolean CultureInvariant)
    {
        int Result;
        Result = 
            (IgnoreCase.Value == true ? RegexOptions.IgnoreCase : RegexOptions.None) ||
            (MultiLine.Value ? RegexOptions.Multiline : RegexOptions.None) ||
            (ExplicitCapture.Value ? RegexOptions.ExplicitCapture : RegexOptions.None) || 
            (Compiled.Value ? RegexOptions.Compiled : RegexOptions.None) || 
            (SingleLine.Value ? RegexOptions.Singleline : RegexOptions.None) || 
            (IgnorePatternWhitespace.Value ? RegexOptions.IgnorePatternWhitespace : RegexOptions.None) || 
            (RightToLeft.Value ? RegexOptions.RightToLeft : RegexOptions.None) || 
            (ECMAScript.Value ? RegexOptions.ECMAScript : RegexOptions.None) || 
            (CultureInvariant.Value ? RegexOptions.CultureInvariant : RegexOptions.None);
        return (Result);
    }

尝试 2

public static object Iif(bool cond, object left, object right)
    {
        return cond ? left : right;
    }

    [SqlFunction(IsDeterministic = true, IsPrecise = true)]
    public static SqlInt32 RegExOptionEnumeration(SqlBoolean IgnoreCase, SqlBoolean MultiLine, SqlBoolean ExplicitCapture, SqlBoolean Compiled, SqlBoolean SingleLine, SqlBoolean IgnorePatternWhitespace, SqlBoolean RightToLeft, SqlBoolean ECMAScript, SqlBoolean CultureInvariant)
    {
        int Result;
        Result = Iif(IgnoreCase.Value, RegexOptions.IgnoreCase, RegexOptions.None) || Iif(MultiLine.Value, RegexOptions.Multiline, RegexOptions.None) || Iif(ExplicitCapture.Value, RegexOptions.ExplicitCapture, RegexOptions.None) || Iif(Compiled.Value, RegexOptions.Compiled, RegexOptions.None) || Iif(SingleLine.Value, RegexOptions.Singleline, RegexOptions.None) || Iif(IgnorePatternWhitespace.Value, RegexOptions.IgnorePatternWhitespace, RegexOptions.None) || Iif(RightToLeft.Value, RegexOptions.RightToLeft, RegexOptions.None) || Iif(ECMAScript.Value, RegexOptions.ECMAScript, RegexOptions.None) || Iif(CultureInvariant.Value, RegexOptions.CultureInvariant, RegexOptions.None);
        return (Result);
    }

【问题讨论】:

  • “但无济于事”究竟是什么意思?
  • telerek 版本有什么问题?
  • 在您正在执行的版本中 ||这是逻辑或,但你想要按位或 |因为它将标志转换为存储在 int 中的位域

标签: c# sql-server vb.net clr sqlclr


【解决方案1】:

我找到了一种无需转换为 C# 即可使用 VB 脚本的方法

项目属性 > SQL CLR > 语言

一旦完成,所有标记为 CLR 的项目都可以使用 VB 风格获得:

似乎 SSDT DB 项目可以使用 C# CLR 或 VB CLR,但不能同时使用两者(尽管两者都可以在 SQL Server 中使用)。

【讨论】:

    【解决方案2】:

    虽然链接文档页面上的措辞确实具有误导性,但它并未声明不支持 VB.NET。您是否尝试过创建 VB.NET 项目?什么是关于出版的“破碎”?我不使用 VB.NET,所以我没有尝试过,但在过去的 16 年中,我也没有听到/看到有人提出过这种说法(自从引入了 SQLCLR 并且人们主要使用 C#,但也绝对是 VB.NET,在较小程度上是 Visual C++,有时,也不是没有痛苦,F#)。

    但是,当我将它带入我们的 SSDT 项目并整合到我们的下一个 .dacpac 版本中时,没有任何效果!

    这与最初使用的语言有什么关系? DLL 的字节码与最初用 C# 编写的字节码相同,对吧?您使用的是什么版本的 SQL Server?这很可能是安全问题,而不是语言问题。

    另外,您带入 SSDT 项目的“它”是什么?原始代码还是已经加载到 SQL Server 中的程序集?这可能是 SSDT 配置问题。

    在任何一种情况下,如果您在使用 VB.NET 代码时收到错误,请首先发布这些错误并确认问题确实是语言而不是许多其他问题。你可能会白白做很多额外的工作,所有这些都是基于一个错误的假设。假设您确实收到消息编号和/或文本错误,您是否查看了其中任何一个?同样,请将这些内容发布到问题中,因为即使使用有效的 C# 代码,您也很可能再次遇到同样的问题。

    另外,只是把它放在那里,如果你想要 RegEx 函数,你可以通过安装 SQL# (SQLsharp) 库(我写的)来完成。免费版包含大部分 RegEx 函数,它们相当完整地表示您可以在 .NET 中使用 RegEx 执行的操作(包括传入 RegExOptions):Match、Matches、Split、Replace、CaptureGroups、CaptureGroupCaptures 等。

    【讨论】:

    • 嗨。感谢您的输入,我将查看您的图书馆。我尝试了各种方法 - 引入程序集并添加引用,将代码引入解决方案中的项目并引用该项目。正如您所说,也许这是一个配置问题,但我注意到的一件事是,如果我在解决方案中添加一个新项目并搜索 CLR,所有项目都是基于 C# 的。我可以继续尝试,但我对 C# 比在 VB 更舒服(尽管我承认 C# 也不是很好!)
    • @Adam 安装 Visual Studio 时,是否安装了 VB.NET 支持?我已经有一段时间没有安装它了,但我认为您必须选择要使用的语言,例如 C#、VB.NET、VC++,而几年前 J# 是一个选项。还是我记错了?
    • 感谢您的建议最终让我找到了答案。问题不在安装程序级别,而是在项目属性级别。我添加了一个包含解决所需步骤的答案。
    【解决方案3】:

    该函数正在使用正则表达式选项的位域构建一个 int(它们的设计方式可以将它们组合在一起)。所以我会写一个实用程序函数并做类似的事情:-

        static int BitIf(SqlBoolean condition, RegexOptions flag) => condition.Value ? (int) flag : 0;
    
        static SqlInt32 RegExOptionEnumeration(SqlBoolean IgnoreCase, SqlBoolean MultiLine, SqlBoolean ExplicitCapture, SqlBoolean Compiled, SqlBoolean SingleLine, SqlBoolean IgnorePatternWhitespace, SqlBoolean RightToLeft, SqlBoolean ECMAScript, SqlBoolean CultureInvariant)
        {
                return BitIf(IgnoreCase, RegexOptions.IgnoreCase)
                | BitIf(MultiLine, RegexOptions.Multiline)
                | BitIf(ExplicitCapture, RegexOptions.ExplicitCapture)
                | BitIf(Compiled, RegexOptions.Compiled)
                | BitIf(SingleLine, RegexOptions.Singleline)
                | BitIf(IgnorePatternWhitespace, RegexOptions.IgnorePatternWhitespace)
                | BitIf(RightToLeft, RegexOptions.RightToLeft)
                | BitIf(ECMAScript, RegexOptions.ECMAScript)
                | BitIf(CultureInvariant, RegexOptions.CultureInvariant);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多