Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Van toepassing op: SQL Server 2019 (15.x) en latere versies
In deze zelfstudie leert u hoe u SQL Server Language Extensions gebruikt om een C#-klasse te maken die twee kolommen (id en tekst) van SQL Server en een reguliere expressie (regex) ontvangt als invoerparameter. De klasse retourneert twee kolommen terug naar SQL Server (id en tekst).
Voor een bepaalde tekst in de tekstkolom die naar de C#-klasse wordt verzonden, controleert de code of aan de opgegeven reguliere expressie is voldaan en wordt die tekst samen met de oorspronkelijke id geretourneerd.
Deze voorbeeldcode maakt gebruik van een reguliere expressie die controleert of een tekst het woord C# bevat of c#.
Vereiste voorwaarden
Database Engine-exemplaar op SQL Server 2019 (15.x) en latere versies, met het uitbreidbaarheidsframework en de .NET-programmeerextensie in Windows. Zie Wat is SQL Server Language Extensions?voor meer informatie. Zie De .NET-runtime aanroepen in SQL Server Language Extensions voor meer informatie over coderingsvereisten.
SQL Server Management Studio of Azure Data Studio voor het uitvoeren van T-SQL.
.NET 6 of hoger SDK in Windows.
Het
dotnet-core-CSharp-lang-extension-windows-release.zipbestand van de Microsoft Extensibility SDK voor C# voor SQL Server.
Compilatie van opdrachtregels is dotnet build voldoende voor deze zelfstudie.
Voorbeeldgegevens maken
Maak eerst een nieuwe database en vul een testdata tabel met ID en text kolommen.
CREATE DATABASE csharptest;
GO
USE csharptest;
GO
CREATE TABLE testdata
(
[id] INT,
[text] VARCHAR (100)
);
GO
INSERT INTO testdata (id, "text") VALUES (4, 'This sentence contains C#');
INSERT INTO testdata (id, "text") VALUES (1, 'This sentence does not');
INSERT INTO testdata (id, "text") VALUES (3, 'I love c#!');
INSERT INTO testdata (id, "text") VALUES (2, NULL);
GO
De hoofdklasse maken
In deze stap maakt u een klassebestand met de naam RegexSample.cs en kopieert u de volgende C#-code naar dat bestand.
Deze hoofdklasse importeert de SDK, wat betekent dat het C#-bestand dat in de eerste stap is gedownload, kan worden gedetecteerd vanuit deze klasse.
using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using Microsoft.Data.Analysis;
using Microsoft.SqlServer.CSharpExtension.SDK;
using System.Text.RegularExpressions;
namespace UserExecutor
{
/// <summary>
/// This class extends the AbstractSqlServerExtensionExecutor and uses
/// a regular expression that checks if a text contains the word "C#" or "c#"
/// </summary>
public class CSharpRegexExecutor: AbstractSqlServerExtensionExecutor
{
/// <summary>
/// This method overrides the Execute method from AbstractSqlServerExtensionExecutor.
/// </summary>
/// <param name="input">
/// A C# DataFrame contains the input dataset.
/// </param>
/// <param name="sqlParams">
/// A Dictionary contains the parameters from SQL server with name as the key.
/// </param>
/// <returns>
/// A C# DataFrame contains the output dataset.
/// </returns>
public override DataFrame Execute(DataFrame input, Dictionary<string, dynamic> sqlParams){
// Drop NULL values and sort by id
//
input = input.DropNulls().OrderBy("id");
// Create empty output DataFrame with two columns
//
DataFrame output = new DataFrame(new PrimitiveDataFrameColumn<int>("id", 0), new StringDataFrameColumn("text", 0));
// Filter text containing specific substring using regex expression
//
DataFrameColumn texts = input.Columns["text"];
for(int i = 0; i < texts.Length; ++i)
{
if(Regex.IsMatch((string)texts[i], sqlParams["@regexExpr"]))
{
output.Append(input.Rows[i], true);
}
}
// Modify the parameters
//
sqlParams["@rowsCount"] = output.Rows.Count;
sqlParams["@regexExpr"] = "Success!";
// Return output dataset as a DataFrame
//
return output;
}
}
}
Een DLL-bestand compileren en maken
Verpakt uw klassen en afhankelijkheden in een DLL. U kunt een .csproj bestand maken met de naam RegexSample.csproj en de volgende code naar dat bestand kopiëren.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<EnableDynamicLoading>true</EnableDynamicLoading>
</PropertyGroup>
<PropertyGroup>
<OutputPath>$(BinRoot)/$(Configuration)/</OutputPath>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Data.Analysis" Version="0.4.0" />
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.SqlServer.CSharpExtension.SDK">
<HintPath>[path]\Microsoft.SqlServer.CSharpExtension.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
Ga naar de projectmap en voer het uit, waarmee het volgende bestand wordt gegenereerd dotnet build:
path\to\project\bin\Debug\RegexSample.dll
Zie Een .NET DLL maken op basis van een C#-project voor meer informatie.
Externe taal maken
U moet een externe taal maken in de database. De externe taal is een database-scoped object, wat betekent dat externe talen zoals C# moeten worden gemaakt voor elke database waarin u deze wilt gebruiken.
Maak een
.zipbestand met de extensie.Als onderdeel van de INSTALLATIE van SQL Server in Windows wordt het .NET-extensiebestand
.zipop deze locatie geïnstalleerd:<SQL Server install path>\MSSQL\Binn>\dotnet-core-CSharp-lang-extension.zip. Dit ZIP-bestand bevat denativecsharpextension.dll.Maak een externe taal
dotnetop basis van het.zipbestand:CREATE EXTERNAL LANGUAGE [dotnet] FROM ( CONTENT = N'<path>\dotnet-core-CSharp-lang-extension.zip', FILE_NAME = 'nativecsharpextension.dll' ); GO
Machtigingen instellen
Als u .NET C#-code wilt uitvoeren, moet de gebruiker SID S-1-15-2-1 (<LocalMachineName>\ALL APPLICATION PACKAGES) leesmachtigingen voor de \MSSQL map krijgen.
- Klik met de rechtermuisknop op de map en kies Eigenschappenbeveiliging>
- Bewerken selecteren
- Selecteer Toevoegen
-
Selecteer gebruikers, computers, serviceaccounts of groepen:
- Objecttypen selecteren en ervoor zorgen dat ingebouwde beveiligingsprincipes en groepen zijn geselecteerd
- Selecteer Locaties om de naam van de lokale computer boven aan de lijst te selecteren
- Voer in
ALL APPLICATION PACKAGES, controleer de naam en selecteer OK om toe te voegen. Als de naam niet wordt omgezet, gaat u opnieuw naar de stap Locaties . De systeem-id (SID) is lokaal op uw computer.
Zie CREATE EXTERNAL LANGUAGE voor meer informatie.
Externe bibliotheken maken
Gebruik CREATE EXTERNAL LIBRARY om een externe bibliotheek te maken voor uw DLL-bestanden. SQL Server heeft toegang tot de .dll bestanden en u hoeft geen speciale machtigingen in te stellen op de classpath.
Maak een externe bibliotheek voor de RegEx-code.
CREATE EXTERNAL LIBRARY [regex.dll]
FROM (CONTENT = N'<path>\RegexSample.dll')
WITH (LANGUAGE = 'Dotnet');
GO
De C#-klasse aanroepen
Roep de opgeslagen procedure sp_execute_external_script aan om de C#-code aan te roepen vanuit SQL Server. Definieer in de scriptparameter welke libraryname;namespace.classname u wilt aanroepen. U kunt ook definiëren welke namespace.classname u wilt aanroepen zonder de naam van de bibliotheek op te geven. De extensie vindt de eerste bibliotheek met de overeenkomende namespace.classnamebibliotheek. In de volgende code behoort de klasse tot een naamruimte die wordt aangeroepen UserExecutor en een klasse met de naam CSharpRegexExecutor.
De code definieert niet welke methode moet worden aangeroepen. Standaard wordt de Execute methode aangeroepen. Dit betekent dat u de SDK-interface moet volgen en een Execute methode in uw C#-klasse moet implementeren als u de klasse vanuit SQL Server wilt kunnen aanroepen.
De opgeslagen procedure gebruikt een invoerquery (invoergegevensset) en een reguliere expressie en retourneert de rijen die aan de opgegeven reguliere expressie hebben voldaan. Er wordt een reguliere expressie [Cc]# gebruikt die controleert of een tekst het woord c#C# of .
DECLARE @rowsCount AS INT;
DECLARE @regexExpr AS VARCHAR (200);
SET @regexExpr = N'[Cc]#';
EXECUTE sp_execute_external_script
@language = N'dotnet',
@script = N'regex.dll;UserExecutor.CSharpRegexExecutor',
@input_data_1 = N'SELECT * FROM testdata',
@params = N'@regexExpr VARCHAR(200) OUTPUT, @rowsCount INT OUTPUT',
@regexExpr = @regexExpr OUTPUT,
@rowsCount = @rowsCount OUTPUT
WITH RESULT SETS
(
(id INT, TEXT VARCHAR (100))
);
SELECT @rowsCount AS rowsCount, @regexExpr AS message;
Results
Nadat de aanroep is uitgevoerd, krijgt u een resultatenset met twee van de rijen.