Beispiel: Angepasster virtueller Tabellen-Provider mit CRUD-Operationen
Dieses Beispiel zeigt, wie Sie einen angepassten Data Provider implementieren, um eine virtuelle Tabelle zu erstellen, die Create-, Retrieve-, Update- und Delete-Operationen unterstützt. Für jede dieser Operationen implementieren Sie ein generisches Plugin, registrieren es mit dem Plugin Registration Tool und aktivieren die Datenquellen der virtuellen Tabelle, um die virtuelle Tabelle zu erstellen.
Um mehr über Datenanbieter und die Entwicklung von Plugins zu erfahren, lesen Sie Angepasste Datenanbieter
Datenquellendetails
In dieser exemplarischen Vorgehensweise werden Sie eine einfache Tabelle in einem externen SQL Server festlegen, um eine virtuelle Tabelle zu erstellen. Der in diesem Beispiel verwendete Tabellenname ist VETicket.
Anmerkung
Aktualisieren Sie Ihren Plugin-Code, wenn Sie den Namen der Tabelle oder der Spalte(n) ändern möchten.
Spaltenname | Datentyp | Zweck |
---|---|---|
TicketID | Eindeutig identifiziert, Primärschlüssel | Primärschlüssel für die Tabelle. |
Schweregrad | Integer | Schweregrad-Wert für das Ticket. |
Name | String | Beschreibung des Tickets. |
Es gibt vier Schritte, damit ein angepasster Datenanbieter eine virtuelle Tabelle erstellen kann.
Schritt 1: Implementieren von CRUD-Plug-ins und Registrieren der Assembly
Schritt 2: Erstellen des Datenproviders und Hinzufügen von Plug-ins zum Provider
Schritt 3: Erstellen einer virtuellen Tabelle in Dataverse-Umgebung
Schritt 1: Implementieren von CRUD-Plug-ins und Registrieren der Assembly
Erstellen Sie Ihr Plug-In-Projekt und installieren Sie die folgenden NuGet-Pakete. Die Lösung in diesem Beispiel heißt StubProvider.
Montage URL Microsoft.CrmSdk.CoreAssemblies https://www.nuget.org/packages/Microsoft.CrmSdk.CoreAssemblies Microsoft.CrmSdk.Data https://www.nuget.org/packages/Microsoft.CrmSdk.Data Microsoft.CrmSdk.Deployment https://www.nuget.org/packages/Microsoft.CrmSdk.Deployment Microsoft.CrmSdk.Workflow https://www.nuget.org/packages/Microsoft.CrmSdk.Workflow Microsoft.CrmSdk.XrmTooling.CoreAssembly https://www.nuget.org/packages/Microsoft.CrmSdk.XrmTooling.CoreAssembly Microsoft.IdentityModel.Clients.ActiveDirectory https://www.nuget.org/packages/Microsoft.IdentityModel.Clients.ActiveDirectory Microsoft.Rest.ClientRuntime https://www.nuget.org/packages/Microsoft.Rest.ClientRuntime Newtonsoft.Json https://www.nuget.org/packages/Newtonsoft.Json/13.0.1-beta2 Fügen Sie die folgenden sechs Klassendateien zu Ihrer Lösung hinzu. Fügen Sie in jeder der Klassendateien die folgenden using-Anweisungen hinzu
using System; using System.Collections.Generic; using System.Data.SqlClient; using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.Xrm.Sdk; using Microsoft.Xrm.Sdk.Extensions; using Microsoft.Xrm.Sdk.Data.Exceptions; using Newtonsoft.Json;
Anmerkung
Aktualisieren Sie in jeder dieser Klassendateien den Tabellennamen, damit er mit dem Namen der Quelltabelle übereinstimmt, die Sie eingerichtet haben. Im Beispiel wird VETicket als Quelltabellenname verwendet.
Name der Klassendatei Zweck Connection.cs Diese Klasse enthält Code zum Erstellen und Verwalten der Verbindung zur externen SQL-Datenquelle. Sie enthält Parameter für die Verbindungszeichenfolge, die für die externe Datenbank spezifisch sind, sowie SQL-basierte Authentifizierungsinformationen, die zum Herstellen der Verbindung erforderlich sind. Ersetzen Sie die Werte entsprechend Ihrer: Datenbankserver, UserID, Kennwort und Tabellenname, die Sie eine virtuelle Tabelle erstellen werden, in Dataverse. CreatePlugin.cs Diese Klasse enthält Code, der den Erstellungsvorgang für die virtuelle Tabelle abwickelt. UpdatePlugin.cs Diese Klasse enthält Code, der das Aktualisieren von Datensätzen in der virtuellen Tabelle behandelt. RetrievePlugin.cs Diese Klasse enthält Code, der einen bestimmten Datensatz aus der virtuellen Tabelle abruft. RetrieveMultiplePlugin.cs Diese Klasse enthält Code zum Abrufen mehrerer Datensätze aus der virtuellen Tabelle. DeletePlugin.cs Diese Klasse enthält Code, der es erlaubt, einen Datensatz in der virtuellen Tabelle zu löschen.
Lesen Sie die folgenden wichtigen Informationen zur Verwendung einer Verbindungszeichenfolge oder zur Authentifizierung mit Benutzername/Kennwort im Anwendungscode.
Wichtig
Microsoft empfiehlt, den sichersten verfügbaren Authentifizierungsflow zu verwenden. Der in diesem Artikel beschriebene Authentifizierungsablauf erfordert ein sehr hohes Maß an Vertrauen in die Anwendung und birgt Risiken, die in anderen Flows nicht vorhanden sind. Sie sollten diesen Flow nur verwenden, wenn andere, sicherere Flows, z. B. verwaltete Identitäten, nicht funktionsfähig sind.
Code für Connection.cs
public static class Connection
{
public static SqlConnection GetConnection()
{
try
{
//sample database to connect to
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
builder.DataSource = "Enter name or network address of the SQL Server";
builder.UserID = "Enter User Name";
builder.Password = "Enter password";
builder.InitialCatalog = "Enter database details";
SqlConnection connection = new SqlConnection(builder.ConnectionString);
return connection;
}
catch (SqlException e)
{
Console.WriteLine(e.ToString());
throw;
}
}
}
Code für CreatePlugin.cs
public class CreatePlugin : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
var context = serviceProvider.Get<IPluginExecutionContext>();
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
{
Entity entity = (Entity)context.InputParameters["Target"];
Guid id = Guid.NewGuid();
//change the table name below to the source table name you have created
string cmdString = "INSERT INTO VETicket (TicketID,Name,Severity) VALUES (@TicketID, @Name, @Severity)";
SqlConnection connection = Connection.GetConnection();
using (SqlCommand command = connection.CreateCommand())
{
command.CommandText = cmdString;
command.Parameters.AddWithValue("@TicketID", id);
command.Parameters.AddWithValue("@Name", entity["new_name"]);
command.Parameters.AddWithValue("@Severity", entity["new_severity"]);
connection.Open();
try
{
var numRecords = command.ExecuteNonQuery();
Console.WriteLine("inserted {0} records", numRecords);
}
finally
{
connection.Close();
}
// other codes.
}
context.OutputParameters["id"] = id;
}
}
}
Code für UpdatePlugin.cs
public class UpdatePlugin: IPlugin {
public void Execute(IServiceProvider serviceProvider)
{
var context = serviceProvider.Get<IPluginExecutionContext>();
Guid id = Guid.Empty;
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
{
Entity entity = (Entity)context.InputParameters["Target"];
//change the table name below to the source table name you have created
string cmdString = "UPDATE VETicket SET {0} WHERE TicketID=@TicketID";
SqlConnection connection = Connection.GetConnection();
using (SqlCommand command = connection.CreateCommand())
{
command.Parameters.AddWithValue("@TicketID", entity["new_ticketid"]);
List<string> setList = new List<string>();
if (entity.Attributes.Contains("new_name"))
{
command.Parameters.AddWithValue("@Name", entity["new_name"]);
setList.Add("Name=@Name");
}
if (entity.Attributes.Contains("new_severity"))
{
command.Parameters.AddWithValue("@Severity", entity["new_severity"]);
setList.Add("Severity=@Severity");
}
command.CommandText = string.Format(cmdString, string.Join(",", setList)); connection.Open();
try
{
var numRecords = command.ExecuteNonQuery();
Console.WriteLine("updated {0} records", numRecords);
}
finally
{
connection.Close();
}
// other codes.
}
}
}
}
Code für RetrievePlugin.cs
public class RetrievePlugin : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
var context = serviceProvider.Get<IPluginExecutionContext>();
Guid id = Guid.Empty;
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is EntityReference)
{
EntityReference entityRef = (EntityReference)context.InputParameters["Target"];
Entity e = new Entity("new_ticket");
//change the table name below to the source table name you have created
string cmdString = "SELECT TicketID, Severity, Name FROM VETicket WHERE TicketID=@TicketID";
SqlConnection connection = Connection.GetConnection();
using (SqlCommand command = connection.CreateCommand())
{
command.CommandText = cmdString;
command.Parameters.AddWithValue("@TicketID", entityRef.Id);
connection.Open();
try
{
using (SqlDataReader reader = command.ExecuteReader())
{
if (reader.Read())
{
e.Attributes.Add("new_ticketid", reader.GetGuid(0));
e.Attributes.Add("new_severity", reader.GetInt32(1));
e.Attributes.Add("new_name", reader.GetString(2));
}
}
}
finally
{
connection.Close();
}
// other codes.
}
context.OutputParameters["BusinessEntity"] = e;
}
}
}
Code für RetrieveMultiplePlugin.cs
public class RetrieveMultiplePlugin : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
var context = serviceProvider.Get<IPluginExecutionContext>();
EntityCollection collection = new EntityCollection();
//change the table name below to the source table name you have created
string cmdString = "SELECT TicketID, Severity, Name FROM VETicket";
SqlConnection connection = Connection.GetConnection();
using (SqlCommand command = connection.CreateCommand())
{
command.CommandText = cmdString;
connection.Open();
try
{
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
Entity e = new Entity("new_ticket");
e.Attributes.Add("new_ticketid", reader.GetGuid(0));
e.Attributes.Add("new_severity", reader.GetInt32(1));
e.Attributes.Add("new_name", reader.GetString(2));
collection.Entities.Add(e);
}
}
}
finally
{
connection.Close();
}
context.OutputParameters["BusinessEntityCollection"] = collection;
}
}
}
Code für DeletePlugin.cs
public class DeletePlugin : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
var context = serviceProvider.Get<IPluginExecutionContext>();
//comment
Guid id = Guid.Empty;
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is EntityReference)
{
EntityReference entityRef = (EntityReference)context.InputParameters["Target"];
id = entityRef.Id;
//change the table name below to the source table name you have created
string cmdString = "DELETE VETicket WHERE TicketID=@TicketID";
SqlConnection connection = Connection.GetConnection();
using (SqlCommand command = connection.CreateCommand())
{
command.CommandText = cmdString; command.Parameters.AddWithValue("@TicketID", id);
connection.Open();
try
{
var numRecords = command.ExecuteNonQuery();
Console.WriteLine("deleted {0} records", numRecords);
}
finally
{
connection.Close();
}
// other codes.
}
}
}
}
Kompilieren und erstellen Sie die Lösung. Sie verfügen nun über eine Assembly-Datei (.dll), die Sie zur Registrierung in Ihrer Dataverse-Umgebung verwenden können. Sie finden diese Datei im Verzeichnis Lösungsordner/bin/Debug.
Registrieren Sie die Assembly mit dem Plugin Registration Tool. Sie können das neueste Plugin Registration Tool-Paket von NuGet erhalten.
Öffnen Sie das Plugin Registration Tool. Sie müssen über Systemadministrationsrechte verfügen, um die Assembly zu registrieren. Wählen Sie NEUE VERBINDUNG ERSTELLEN, um eine Verbindung zu Ihrer Dataverse-Umgebung herzustellen. Wählen Sie das Dropdown-Menü Registrieren, und wählen Sie dann Neue Assembly registrieren.
Wählen Sie die Assembly-Datei und registrieren Sie die Plug-ins. Vergewissern Sie sich, dass Sie alle Plug-ins ausgewählt haben (Create-, Update-, Delete-, Retrieve- und RetrieveMultiple-Plug-ins).
Schritt 2: Erstellen des Datenproviders und Hinzufügen von Plug-ins zum Provider
Wählen Sie das Dropdown-Menü Registrieren und dann Neuen Datenprovider registrieren.
Geben Sie im Dialog Neuen Datenanbieter registrieren die folgenden Details ein:
Geben Sie Datenprovider-Name ein.
Wählen Sie in der Option Lösungen eine vorhandene Lösung aus oder erstellen Sie eine neue Lösung in der Dropdown-Liste. Wenn Sie eine neue Lösung erstellen wollen, wählen Sie in der Dropdown-Liste die Option NewSolution. Geben Sie im Dialog Neue Lösung erstellen die erforderlichen Details ein und wählen Sie Speichern.
Wählen Sie in der Option Datentabellenquelle (Entität) die Option Neue Datenquelle erstellen. Geben Sie die Details ein. Stellen Sie sicher, dass die Datenquelle Teil der Lösung ist, die Sie erstellt oder ausgewählt haben.
Anmerkung
Die Datenquellentabelle in Dataverse enthält die Konfigurationsdaten für einen Datensatz der Datenquelle, der an die Provider-Plug-ins übergeben werden soll.
Ordnen Sie jedes der registrierten Plug-Ins den jeweiligen Operationen zu.
Registrieren Sie den neuen Datenanbieter.
Im Plugin Registration Tool sehen Sie den neuen Datensatz der Datenquelle und den zugehörigen Datenanbieter. Wenn Sie die Datenquelle auswählen, werden die Details angezeigt, die die Plug-ins und ihre registrierte GUID enthalten.
Schritt 3: Erstellen einer virtuellen Tabelle in Dataverse-Umgebung
Erstellen Sie eine neue Datenquelle für eine virtuelle Tabelle, indem Sie zu Einstellungen>Verwaltung>Virtuelle Tabelle (Entitäten)-Datenquellen navigieren.
Wählen Sie Neu und wählen Sie dann den Datenanbieter, den Sie im vorherigen Schritt erstellt haben, aus der Dropdown-Liste.
Geben Sie einen Namen für die Datenquelle ein und wählen Sie Speichern und schließen.
Jetzt können Sie die virtuelle Tabelle erstellen, die die externe Datenquelle darstellt. Gehen Sie dazu auf Einstellungen>Anpassen des Systems.
Wählen Sie im linken Navigationsbereich des Lösungsexplorers Tabellen (Entitäten) und dann Neu.
Geben Sie die folgenden Details ein:
Spalte Beschreibung Datenquelle Wählen Sie die Datenquelle, die Sie im vorherigen Schritt erstellt haben. Anzeigename Virtueller Tabellenname. Pluralname Der Wert wird automatisch auf der Basis des Anzeigenamens ausgefüllt. Name Dieser wird ebenfalls automatisch erstellt, basierend auf dem Wert, den Sie für den Anzeigenamen eingeben. Externer Name Der Name der Quelltabelle. Externe Sammlungen Name Sie können denselben Wert aus der Spalte Pluralname verwenden. Wählen Sie Speichern und schließen aus.
Wählen Sie im linken Navigationsbereich die von Ihnen erstellte virtuelle Tabelle aus und erweitern Sie sie.
Wählen Sie Felder, um neue Spalten zu aktualisieren und zu erstellen, die die externe Quelle darstellen.
Wählen Sie die Spalte Primärschlüssel für die virtuelle Tabelle und wählen Sie Bearbeiten.
Aktualisieren Sie die Spalte Externer Name, damit sie mit dem Spaltennamen in Ihrer externen Datenquelle übereinstimmt. In diesem Beispiel lautet der Name der externen Spalte TicketID.
Wählen Sie Speichern und Schließen.
Markieren Sie das Feld Name für die virtuelle Tabelle und wählen Sie Bearbeiten.
Aktualisieren Sie das Feld Externer Name, damit es mit dem Feldnamen in Ihrer externen Datenquelle übereinstimmt. In diesem Beispiel lautet der Name der externen Spalte Name.
Wählen Sie Speichern und Schließen.
Wählen Sie Neu, um eine neue Spalte in der virtuellen Tabelle zu erstellen. Diese Spalte wird die Schweregrad-Spalte in der externen Datenquelle darstellen.
Geben Sie die folgenden Informationen für die neuen Spalten ein:
Spaltenname Wert Anzeigename Schweregrad Name new_severity Externer Name Schweregrad Feldanforderung Eingabe erforderlich Datentyp Ganze Zahl Wählen Sie Speichern und Schließen.
Schritt 4: Datensätze mit einer virtuellen Tabelle erstellen, aktualisieren, anzeigen und löschen
Erstellen Sie eine modellbasierte App und fügen Sie die virtuelle Tabelle der Site-Map zu. Wählen Sie dann das Hauptformular der virtuellen Tabelle und die Ansicht „Erweitertes Feld“. Veröffentlichen Sie die App. Weitere Informationen: Erstellen Sie Ihre erste modellbasierte App von Grund auf
Benutzer der Anwendung können mit der virtuellen Tabelle Lese-, Erstellungs-, Aktualisierungs- und Löschvorgänge durchführen, wie mit jeder anderen Tabelle in Microsoft Dataverse.
Siehe auch
Einstieg in virtuelle Tabellen
API-Überlegungen für virtuelle Tabellen
Anbieter von benutzerdefinierter virtueller Tabellendaten
Beispielhafte Vorgehensweise für virtuelle Tabellen mit OData v4 Data Provider