2016-04-04 15 views
1

Ich verstehe die Einschränkungen von SQLCLR-Aggregaten in Bezug auf den Datenzugriff. Gibt es eine Möglichkeit (einen Workaround), um Ergebnisse in einer Tabelle zu speichern? Es muss innerhalb von SQLCLR-Aggregaten liegen.Datenzugriff innerhalb von benutzerdefinierten SQLCLR-Aggregaten (UDA)

+1

was genau versuchen Sie zu erreichen? Bitte erklären Sie den Prozess, da dies möglicherweise nicht das ist, was Sie tun möchten. –

+0

Ich schätze die Antworten aller; Ich frage jedoch nicht nach Code/Design Reviews oder Kritiken. Ich möchte nur wissen, gibt es eine Problemumgehung für den Zugriff auf Daten im Kontext einer benutzerdefinierten Aggregatfunktion? –

Antwort

0

Warum müssen Sie das Gesamtergebnis in einer Tabelle innerhalb des benutzerdefinierten Aggregats (User-Defined Aggregate, UDA) speichern? Das macht wenig bis gar kein Gefühl gegeben, dass Sie die Ergebnisse in eine Tabelle mit Normalpapier T-SQL speichern:

INSERT INTO SchemaName.TableName (Col1, Col2, ...) 
    SELECT tab.SomeColumn, SchemaName.CustomAggregate(tab.OtherColumn) 
    FROM SchemaName.TableName tab 
    GROUP BY tab.SomeColumn; 

Im Wesentlichen diese das gleiche funktioniert, als ob Sie die Ergebnisse einen der Aggregatfunktionen in integrierten wurden Speicherung , wie zum Beispiel: SUM, MIN, MAX, COUNT, AVG usw.

wenn Sie jedoch haben brauchen dies aus irgendeinem Grund zu tun, verwenden Sie nur eine externe Verbindung (dh nichtContext Connection = true;) in der Terminate() Methode der UDA.

Bitte beachten Sie, dass ein solcher Datenzugriff erforderlich ist, dass die Verbindung nicht versucht, in den aktuellen Transaktionskontext einzutragen (und die Anwerbung ist das Standardverhalten). Dies bedeutet, dass Ihre Verbindungszeichenfolge das folgende Schlüsselwort und den folgenden Wert enthalten muss: Enlist = false;. Und das funktioniert, wie ich erfolgreich in einer Terminate() Methode verwendet habe, und vor dem Hinzufügen der Enlist=false; Ich bekam auch die "Datenzugriff ist in diesem Kontext nicht zulässig. Entweder der Kontext ist eine Funktion oder Methode nicht mit DataAccessKind markiert .Read oder SystemDataAccessKind.Read ist ein Rückruf zum Abrufen von Daten aus der FillRow-Methode einer Tabellenwertfunktion oder einer UDT-Validierungsmethode. "Fehler.

using (SqlConnection _Connection = 
        new SqlConnection("Trusted_Connection=true; Enlist=false;")) 
{ 
    using (SqlCommand _Command = _Connection.CreateCommand()) 
    { 
     _Command.CommandText = "SELECT TOP 1 * FROM sys.objects;"; 
     _Connection.Open(); 
     _Command.ExecuteNonQuery(); 
    } 
} 

Bitte beachten Sie auch, dass eine regelmäßige/externe Verbindung macht die Montage braucht man als EXTERNAL_ACCESS markiert werden. Doch das macht nicht die Datenbank erfordern auf TRUSTWORTHY ON werden: Sie gerade die Versammlung anmelden, erstellen Sie einen asymmetrischen Schlüssel in master von dieser DLL/Montage, erstellen Sie eine Anmeldung aus, dass asymmetrische Schlüssel, und schließlich GRANT, die die EXTERNAL ACCESS ASSEMBLY Erlaubnis Anmelden .

+0

Der Zugriff auf Daten innerhalb einer UDA ist nicht möglich. Ausnahme: System.InvalidOperationException: Datenzugriff ist in diesem Kontext nicht zulässig. –

+0

@ T.Nguyen Ich aktualisierte meine Antwort, um eine Klarstellung hinzuzufügen. Es funktioniert, wenn Sie "Enlist = false;" zum ConnectionString hinzufügen. –

+1

Die Einliste = false; funktioniert perfekt. Vielen Dank! –

0

Sobald Sie die aggregierten Ergebnisse in der C# -Funktion bereit haben, verwenden Sie C# ADO.NET (für Datenbankoperationen), um diese Aggregate in der Datenbank zu speichern. Dies wird innerhalb Ihrer SQL CLR-Funktion sein, so dass Sie die SQL CLR-Funktion einmal aus der Datenbank aufrufen und die Aggregate in einer Tabelle speichern.

Verwandte Themen