How can I convert below VB.net SQL CLR function to C# CLR Function for a VS SSDT SQL Project?
I need to convert it to C# as it seems that built-in SSDT Project support for CLR functions is C# only? If I could find a way to use the original VB in a way that's compatible with VS SSDT projects and won't break Publish workflow, then I would accept that answer! I found it really easy to compile the .dll into SQL server using T-SQL commands in SSMS... but as soon as I brought it into our SSDT project to incorporate into our next .dacpac release, nothing worked!
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)
I have attempted to run the Class through Telerik C# Converter.
Telerik produces below 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);
}
}
All other functions in the Class seem to convert OK with the Telerik converter. I tried searching around for this and it seems that IIf is similar to ternary operators. On this basis, I have tried the following 2 examples, but nothing works...
Attempt 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);
}
Attempt 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);
}
The function is building an int with the bitfields of the regex options (which are designed in such a way they can be combined together). So I'd write a utility function and do it something like :-
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);
}
}