# Adressraum bearbeiten

> Anleitung: Nodes und Verweise im Adressraum eines Servers vom Client aus erstellen und löschen.

**Beispielanwendungen:**

- Client.ClientAddedNodesWithHistory ([C#](https://github.com/Traeger-GmbH/opcuanet-samples/tree/master/cs/Scenarios/Client.ClientAddedNodesWithHistory), [VB.NET](https://github.com/Traeger-GmbH/opcuanet-samples/tree/master/vb/Scenarios/Client.ClientAddedNodesWithHistory)): Legt am Server einen Variablen-Node mit Historie an und schreibt Werte, die der Server in die Historie übernimmt.
- Server.ClientAddedNodesWithHistory ([C#](https://github.com/Traeger-GmbH/opcuanet-samples/tree/master/cs/Scenarios/Server.ClientAddedNodesWithHistory), [VB.NET](https://github.com/Traeger-GmbH/opcuanet-samples/tree/master/vb/Scenarios/Server.ClientAddedNodesWithHistory)): Erlaubt Clients, Variablen-Nodes mit Historie anzulegen, und zeichnet die geschriebenen Werte als Historie auf.

## Nodes anlegen

Beteiligte Typen: `OpcClient`, `OpcAddNode`, `OpcAddNodeResult`, `OpcAddNodeResultCollection`, `OpcAddDataItemNode`, `OpcAddAnalogItemNode`, `OpcAddObjectNode`, `OpcAddFolderNode`, `OpcAddDataVariableNode`, `OpcAddPropertyNode`

Ein Server stellt seinen Clients einen vordefinierten Satz an Standard-Nodes bereit. Ein Client kann den Server veranlassen, weitere Nodes bereitzustellen. Dafür nutzt er die Schnittstelle `AddNodes` des Servers. Für typspezifische Nodes bietet das SDK zahlreiche Unterklassen der Klasse `OpcAddNode`. So legen Sie einen neuen Ordner-Node an:

```csharp
OpcAddNodeResult result = client.AddNode(new OpcAddFolderNode(
    name: "Jobs",
    nodeId: OpcNodeId.Null,
    parentNodeId: "ns=2;s=Machine"));

```

```vbnet
Dim result As OpcAddNodeResult = client.AddNode(New OpcAddFolderNode( _
        name:="Jobs", _
        nodeId:=OpcNodeId.Null, _
        parentNodeId:="ns=2;s=Machine"))

```

Die Parameter im Beispiel enthalten die mindestens nötigen Angaben. Der erste Parameter `name` legt den Namen (Eigenschaft `Name`, der BrowseName des Nodes) und den Anzeigenamen (Eigenschaft `DisplayName`) des Nodes fest. Eine Beschreibung legen Sie über die Eigenschaft `Description` fest. Der zweite Parameter `nodeId` gibt dem Server vor, welchen Identifier er dem Node zuweisen soll. Wenn ein anderer Node im Adressraum des Servers diesen Identifier bereits verwendet, legt der Server den Node nicht an. Ein mit dem SDK entwickelter Server liefert dann den Code `BadNodeIdRejected`, andere Server liefern unter Umständen `BadNodeIdExists`. Wenn Sie wie im Beispiel `OpcNodeId.Null` übergeben, erzeugt der Server selbst einen neuen Identifier und weist ihn dem Node zu. Der Parameter `parentNodeId` legt schließlich den Identifier des Eltern-Nodes fest, unter dem der Server den neuen Node im Baum anlegt. Wenn kein Eltern-Node angegeben ist, legt der Server den Node unterhalb des ObjectsFolder an.

Der Aufruf der Methode `AddNode` liefert eine Instanz der Klasse `OpcAddNodeResult`. Sie enthält neben dem Ausgang der Operation auch den Identifier, den der Server tatsächlich für den neuen Node verwendet hat:

```csharp
if (result.IsGood)
    Console.WriteLine("NodeId of 'Jobs': {0}", result.NodeId);
else
    Console.WriteLine("Failed to add node: {0}", result.Description);

```

```vbnet
If result.IsGood Then
    Console.WriteLine("NodeId of 'Jobs': {0}", result.NodeId)
Else
    Console.WriteLine("Failed to add node: {0}", result.Description)
End If
```

So legen Sie mehrere Nodes gleichzeitig an:

```csharp
OpcNodeId jobsNodeId = result.NodeId;
 
OpcAddNodeResultCollection results = client.AddNodes(
        new OpcAddDataVariableNode<string>("CurrentJob", jobsNodeId),
        new OpcAddDataVariableNode<string>("NextJob", jobsNodeId),
        new OpcAddDataVariableNode<int>("NumberOfJobs", jobsNodeId));

```

```vbnet
Dim jobsNodeId As OpcNodeId = result.NodeId

Dim results As OpcAddNodeResultCollection = client.AddNodes( _
        New OpcAddDataVariableNode(Of String)("CurrentJob", jobsNodeId), _
        New OpcAddDataVariableNode(Of String)("NextJob", jobsNodeId), _
        New OpcAddDataVariableNode(Of Integer)("NumberOfJobs", jobsNodeId))

```

Der Aufruf der Methode `AddNodes` liefert eine Instanz der Klasse `OpcAddNodeResultCollection`. Sie enthält Instanzen von `OpcAddNodeResult`, die Sie wie oben beschrieben auswerten und weiterverarbeiten.

Den Methoden `AddNode` und `AddNodes` können Sie auch ganze Bäume von Nodes übergeben:

```csharp
OpcAddNodeResultCollection results = client.AddNodes(
        new OpcAddObjectNode(
                "JOB001",
                nodeId: OpcNodeId.Null,
                parentNodeId: jobsNodeId,
                new OpcAddDataVariableNode<sbyte>("Status", -1),
                new OpcAddDataVariableNode<string>("Serial", "J01-DX-11.001"),
                new OpcAddAnalogItemNode<float>("Speed", 1200f) {
                    EngineeringUnit = new OpcEngineeringUnitInfo(5067859, "m/s", "metre per second"),
                    EngineeringUnitRange = new OpcValueRange(5400, 0),
                    Definition = "DB100.DBW 0"
                },
                new OpcAddObjectNode(
                        "Setup",
                        new OpcAddPropertyNode<bool>("UseCutter"),
                        new OpcAddPropertyNode<bool>("UseDrill")),
                new OpcAddObjectNode(
                        "Schedule",
                        new OpcAddPropertyNode<DateTime>("EarliestStartTime"),
                        new OpcAddPropertyNode<DateTime>("LatestStartTime"),
                        new OpcAddPropertyNode<TimeSpan>("EstimatedRunTime"))),
        new OpcAddObjectNode(
                "JOB002",
                nodeId: OpcNodeId.Null,
                parentNodeId: jobsNodeId,
                new OpcAddDataVariableNode<sbyte>("Status", -1),
                new OpcAddDataVariableNode<string>("Serial", "J01-DX-53.002"),
                new OpcAddAnalogItemNode<float>("Speed", 3210f) {
                    EngineeringUnit = new OpcEngineeringUnitInfo(5067859, "m/s", "metre per second"),
                    EngineeringUnitRange = new OpcValueRange(5400, 0),
                    Definition = "DB200.DBW 0"
                },
                new OpcAddObjectNode(
                        "Setup",
                        new OpcAddPropertyNode<bool>("UseCutter"),
                        new OpcAddPropertyNode<bool>("UseDrill")),
                new OpcAddObjectNode(
                        "Schedule",
                        new OpcAddPropertyNode<DateTime>("EarliestStartTime"),
                        new OpcAddPropertyNode<DateTime>("LatestStartTime"),
                        new OpcAddPropertyNode<TimeSpan>("EstimatedRunTime"))));

```

```vbnet
Dim results As OpcAddNodeResultCollection = client.AddNodes( _
        New OpcAddObjectNode( _
                "JOB001", _
                nodeId:=OpcNodeId.Null, _
                parentNodeId:=jobsNodeId, _
                New OpcAddDataVariableNode(Of SByte)("Status", -1), _
                New OpcAddDataVariableNode(Of String)("Serial", "J01-DX-11.001"), _
                New OpcAddAnalogItemNode(Of Single)("Speed", 1200F) With {
                    .EngineeringUnit = New OpcEngineeringUnitInfo(5067859, "m/s", "metre per second"),
                    .EngineeringUnitRange = New OpcValueRange(5400, 0),
                    .Definition = "DB100.DBW 0"
                }, _
                New OpcAddObjectNode( _
                        "Setup", _
                        New OpcAddPropertyNode(Of Boolean)("UseCutter"), _
                        New OpcAddPropertyNode(Of Boolean)("UseDrill")), _
                New OpcAddObjectNode( _
                        "Schedule", _
                        New OpcAddPropertyNode(Of DateTime)("EarliestStartTime"), _
                        New OpcAddPropertyNode(Of DateTime)("LatestStartTime"), _
                        New OpcAddPropertyNode(Of TimeSpan)("EstimatedRunTime"))), _
        New OpcAddObjectNode( _
                "JOB002", _
                nodeId:=OpcNodeId.Null, _
                parentNodeId:=jobsNodeId, _
                New OpcAddDataVariableNode(Of SByte)("Status", -1), _
                New OpcAddDataVariableNode(Of String)("Serial", "J01-DX-53.002"), _
                New OpcAddAnalogItemNode(Of Single)("Speed", 3210F) With {
                    .EngineeringUnit = New OpcEngineeringUnitInfo(5067859, "m/s", "metre per second"),
                    .EngineeringUnitRange = New OpcValueRange(5400, 0),
                    .Definition = "DB200.DBW 0" _
                }, _
                New OpcAddObjectNode( _
                        "Setup", _
                        New OpcAddPropertyNode(Of Boolean)("UseCutter"), _
                        New OpcAddPropertyNode(Of Boolean)("UseDrill")), _
                New OpcAddObjectNode( _
                        "Schedule", _
                        New OpcAddPropertyNode(Of DateTime)("EarliestStartTime"), _
                        New OpcAddPropertyNode(Of DateTime)("LatestStartTime"), _
                        New OpcAddPropertyNode(Of TimeSpan)("EstimatedRunTime"))))

```

Einen solchen Baum können Sie auch über die zugehörigen Eigenschaften aufbauen:

```csharp
var jobsNodeId = result.NodeId;
 
var job = new OpcAddObjectNode(
        name: "JOB003",
        nodeId: OpcNodeId.Null,
        parentNodeId: jobsNodeId);
 
job.Children.Add(new OpcAddDataVariableNode<sbyte>("Status", -1));
job.Children.Add(new OpcAddDataVariableNode<string>("Serial", "J01-DX-78.003"));
job.Children.Add(new OpcAddAnalogItemNode<float>("Speed", 1200f) {
    EngineeringUnit = new OpcEngineeringUnitInfo(5067859, "m/s", "metre per second"),
    EngineeringUnitRange = new OpcValueRange(5400, 0),
    Definition = "DB100.DBW 0"
});
 
var setup = new OpcAddObjectNode("Setup");
setup.Children.Add(new OpcAddPropertyNode<bool>("UseCutter"));
setup.Children.Add(new OpcAddPropertyNode<bool>("UseDrill"));
 
job.Children.Add(setup);
 
var schedule = new OpcAddObjectNode("Schedule");
schedule.Children.Add(new OpcAddPropertyNode<DateTime>("EarliestStartTime"));
schedule.Children.Add(new OpcAddPropertyNode<DateTime>("LatestStartTime"));
schedule.Children.Add(new OpcAddPropertyNode<TimeSpan>("EstimatedRunTime"));
 
job.Children.Add(schedule);
 
OpcAddNodeResult result = client.AddNode(job);

```

```vbnet
Dim jobsNodeId = result.NodeId
 
Dim job = New OpcAddObjectNode( _
        name:="JOB003", _
        nodeId:=OpcNodeId.Null, _
        parentNodeId:=jobsNodeId)
 
job.Children.Add(New OpcAddDataVariableNode(Of SByte)("Status", -1))
job.Children.Add(New OpcAddDataVariableNode(Of String)("Serial", "J01-DX-78.003"))
job.Children.Add(new OpcAddAnalogItemNode(Of Single)("Speed", 1200f) With {
    .EngineeringUnit = new OpcEngineeringUnitInfo(5067859, "m/s", "metre per second"),
    .EngineeringUnitRange = new OpcValueRange(5400, 0),
    .Definition = "DB100.DBW 0" _
})
 
Dim setup = New OpcAddObjectNode("Setup")
setup.Children.Add(New OpcAddPropertyNode(Of Boolean)("UseCutter"))
setup.Children.Add(New OpcAddPropertyNode(Of Boolean)("UseDrill"))

job.Children.Add(setup)

Dim schedule = New OpcAddObjectNode("Schedule")
schedule.Children.Add(New OpcAddPropertyNode(Of DateTime)("EarliestStartTime"))
schedule.Children.Add(New OpcAddPropertyNode(Of DateTime)("LatestStartTime"))
schedule.Children.Add(New OpcAddPropertyNode(Of TimeSpan)("EstimatedRunTime"))

job.Children.Add(schedule)

Dim result As OpcAddNodeResult = client.AddNode(job)

```

Wenn Sie andere Typdefinitionen verwenden möchten als die der Unterklassen von `OpcAddNode`, legen Sie Objekt- und Variablen-Nodes anhand ihrer Typdefinition an:

```csharp
client.AddObjectNode(OpcObjectType.DeviceFailureEventType, "FailureInfo");
client.AddVariableNode(OpcVariableType.XYArrayItem, "Coordinates");

```

```vbnet
client.AddObjectNode(OpcObjectType.DeviceFailureEventType, "FailureInfo")
client.AddVariableNode(OpcVariableType.XYArrayItem, "Coordinates")

```

Neben den von der Foundation definierten Typdefinitionen können Sie Nodes auch anhand des Identifiers ihrer Typdefinition anlegen. Dazu deklarieren Sie den Typ vorab über eine objekt- beziehungsweise variablenspezifische Typdefinition. `OpcNodeId.Parse` erzeugt den Identifier der Typdefinition aus seiner Zeichenfolge. Diesen Identifier verwenden Sie beliebig oft, um weitere Nodes dieses Typs zu erstellen:

```csharp
// Declare Job Type
var jobType = OpcAddObjectNode.OfType(OpcNodeId.Parse("ns=2;s=Types/JobType"));
 
client.AddNodes(
        jobType.Create("JOB001", nodeId: OpcNodeId.Null, parentNodeId: jobsNodeId),
        jobType.Create("JOB002", nodeId: OpcNodeId.Null, parentNodeId: jobsNodeId),
        jobType.Create("JOB003", nodeId: OpcNodeId.Null, parentNodeId: jobsNodeId),
        jobType.Create("JOB004", nodeId: OpcNodeId.Null, parentNodeId: jobsNodeId));
 
var scheduleNodeId = OpcNodeId.Parse("ns=2;s=Machine/JOB002/Schedule");
 
// Declare Shift Time Type
var shiftTimeType = OpcAddVariableNode.OfType(OpcNodeId.Parse("ns=2;s=Types/ShiftTimeType"));
 
OpcAddNodeResult result = client.AddNode(new OpcAddObjectNode(
        "ShiftPlanning",
        nodeId: OpcNodeId.Null,
        parentNodeId: scheduleNodeId,
        shiftTimeType.Create("Early"),
        shiftTimeType.Create("Noon"),
        shiftTimeType.Create("Late")));
```

```vbnet
'Declare Job Type
Dim jobType = OpcAddObjectNode.OfType(OpcNodeId.Parse("ns=2;s=Types/JobType"))

client.AddNodes( _
        jobType.Create("JOB001", nodeId:=OpcNodeId.Null, parentNodeId:=jobsNodeId), _
        jobType.Create("JOB002", nodeId:=OpcNodeId.Null, parentNodeId:=jobsNodeId), _
        jobType.Create("JOB003", nodeId:=OpcNodeId.Null, parentNodeId:=jobsNodeId), _
        jobType.Create("JOB004", nodeId:=OpcNodeId.Null, parentNodeId:=jobsNodeId))

Dim scheduleNodeId = OpcNodeId.Parse("ns=2;s=Machine/JOB002/Schedule")

'Declare Shift Time Type
Dim shiftTimeType = OpcAddVariableNode.OfType(OpcNodeId.Parse("ns=2;s=Types/ShiftTimeType"))

Dim result As OpcAddNodeResult = client.AddNode(New OpcAddObjectNode( _
        "ShiftPlanning", _
        nodeId:=OpcNodeId.Null, _
        parentNodeId:=scheduleNodeId, _
        shiftTimeType.Create("Early"), _
        shiftTimeType.Create("Noon"), _
        shiftTimeType.Create("Late")))
```

## Nodes löschen

Beteiligte Typen: `OpcClient`, `OpcDeleteNode`, `OpcStatus`, `OpcStatusCollection`

Über die Schnittstelle `DeleteNodes` des Servers löschen Sie sowohl vom Server bereitgestellte als auch von einem Client erstellte Nodes. Dafür benötigen Sie vor allem den Identifier des Nodes, den Sie löschen möchten:

```csharp
OpcStatus result = client.DeleteNode("ns=2;s=Machine/Jobs");

```

```vbnet
Dim result As OpcStatus = client.DeleteNode("ns=2;s=Machine/Jobs")

```

Das Beispiel oben löscht mit einer Instanz der Klasse `OpcDeleteNode`. Sie löscht standardmäßig auch alle Verweise, die auf den Node zeigen. Wenn die Verweise auf den Node bestehen bleiben sollen, setzen Sie zusätzlich den Parameter `includeTargetReferences` auf `false`:

```csharp
OpcStatus result = client.DeleteNode(
        "ns=2;s=Machine/Jobs",
        includeTargetReferences: false);

```

```vbnet
Dim result As OpcStatus = client.DeleteNode( _
        "ns=2;s=Machine/Jobs", _
        includeTargetReferences:=False)

```

So löschen Sie mehrere Nodes gleichzeitig:

```csharp
OpcStatusCollection results = client.DeleteNodes(
        new OpcDeleteNode("ns=2;s=Machine/Jobs/JOB001"),
        new OpcDeleteNode("ns=2;s=Machine/Jobs/JOB002"),
        new OpcDeleteNode("ns=2;s=Machine/Jobs/JOB003"));

```

```vbnet
Dim results As OpcStatusCollection = client.DeleteNodes( _
        New OpcDeleteNode("ns=2;s=Machine/Jobs/JOB001"), _
        New OpcDeleteNode("ns=2;s=Machine/Jobs/JOB002"), _
        New OpcDeleteNode("ns=2;s=Machine/Jobs/JOB003"))

```

## Verweise anlegen

Beteiligte Typen: `OpcClient`, `OpcAddReference`, `OpcStatus`, `OpcStatusCollection`

Nodes im Adressraum eines Servers können unterschiedliche Beziehungen zueinander haben. Der Adressraum beschreibt diese Beziehungen über Verweise (engl. References). Neben der Einordnung als Eltern- oder Kind-Node können zwischen Nodes weitere logische Beziehungen bestehen. Diese Beziehungen beschreiben genauer, welche Funktion die Nodes haben und wie sie voneinander abhängen. Außerdem lassen sich über Verweise weitere Bäume im Adressraum des Servers definieren, ohne vorhandene Nodes neu zu organisieren.

Um einen Verweis anzulegen, nutzt der Client die Schnittstelle `AddReferences` des Servers:

```csharp
client.AddReference(
        "ns=2;s=Plant",
        targetNodeId: "ns=2;s=Machines/MAC01",
        targetNodeCategory: OpcNodeCategory.Object);
```

```vbnet
client.AddReference( _
        "ns=2;s=Plant", _
        targetNodeId:="ns=2;s=Machines/MAC01", _
        targetNodeCategory:=OpcNodeCategory.Object)
```

Das Beispiel erzeugt einen Verweis vom Typ Organizes, der vom Node mit dem Identifier `ns=2;s=Plant` zum Node `ns=2;s=Machines/MAC01` führt. Standardmäßig verwendet der Client den Verweistyp Organizes und die Richtung `OpcReferenceDirection.ParentToChild`. Bei dieser Richtung wird der erste Node zum Eltern-Node. Die Anweisung führt damit zum selben Ergebnis wie das folgende Beispiel:

```csharp
client.AddReference(
        "ns=2;s=Plant",
        targetNodeId: "ns=2;s=Machines/MAC01",
        targetNodeCategory: OpcNodeCategory.Object,
        direction: OpcReferenceDirection.ParentToChild,
        referenceType: OpcReferenceType.Organizes);
```

```vbnet
client.AddReference( _
        "ns=2;s=Plant", _
        targetNodeId:="ns=2;s=Machines/MAC01", _
        targetNodeCategory:=OpcNodeCategory.Object, _
        direction:=OpcReferenceDirection.ParentToChild, _
        referenceType:=OpcReferenceType.Organizes)
```

Der erste Identifier gibt immer den Quell-Node an, der Parameter `targetNodeId` den Identifier des Ziel-Nodes. Mit der Richtung `OpcReferenceDirection.ChildToParent` legt der Client den Verweis stattdessen vom Ziel-Node zum Quell-Node an. Der zusätzliche Parameter `targetNodeCategory` muss der Eigenschaft `Category` des Ziel-Nodes entsprechen, in der Spezifikation die NodeClass. Anhand dieses Werts stellt der Server sicher, dass der gewünschte Ziel-Node ausreichend bekannt ist.

So legen Sie mehrere Verweise gleichzeitig an:

```csharp
client.AddReferences(
        new OpcAddReference(
                "ns=2;s=Plant01",
                targetNodeId: "ns=2;s=Machines/MAC01",
                targetNodeCategory: OpcNodeCategory.Object),
        new OpcAddReference(
                "ns=2;s=Plant01",
                targetNodeId: "ns=2;s=Machines/MAC02",
                targetNodeCategory: OpcNodeCategory.Object),
        new OpcAddReference(
                "ns=2;s=Plant02",
                targetNodeId: "ns=2;s=Machines/MAC03",
                targetNodeCategory: OpcNodeCategory.Object));
```

```vbnet
client.AddReferences( _
        New OpcAddReference( _
                "ns=2;s=Plant01", _
                targetNodeId:="ns=2;s=Machines/MAC01", _
                targetNodeCategory:=OpcNodeCategory.Object), _
        New OpcAddReference( _
                "ns=2;s=Plant01", _
                targetNodeId:="ns=2;s=Machines/MAC02", _
                targetNodeCategory:=OpcNodeCategory.Object), _
        New OpcAddReference( _
                "ns=2;s=Plant02", _
                targetNodeId:="ns=2;s=Machines/MAC03", _
                targetNodeCategory:=OpcNodeCategory.Object))
```

Das Beispiel oben ordnet drei Nodes zusätzlich unterhalb der Nodes „Plant01“ und „Plant02“ ein. Jeder dieser Nodes repräsentiert eine Maschine und liegt unterhalb des Nodes „Machines“. Durch den standardmäßig verwendeten Verweistyp Organizes bleiben die Nodes weiterhin unterhalb von „Machines“ verfügbar. Zusätzlich erscheinen „MAC01“ und „MAC02“ unterhalb von „Plant01“ und „MAC03“ unterhalb von „Plant02“.

## Verweise löschen

Beteiligte Typen: `OpcClient`, `OpcDeleteReference`, `OpcStatus`, `OpcStatusCollection`

Bestehende Verweise zwischen Nodes im Adressraum des Servers löschen Sie über die Schnittstelle `DeleteReferences` des Servers:

```csharp
client.DeleteReference(
        nodeId: "ns=2;s=Machines/MAC03",
        targetNodeId: "ns=2;s=Plant");

```

```vbnet
client.DeleteReference( _
        nodeId:="ns=2;s=Machines/MAC03", _
        targetNodeId:="ns=2;s=Plant")

```

Das Beispiel löscht alle Organizes-Verweise zwischen den Nodes mit den Identifiern `ns=2;s=Machines/MAC03` und `ns=2;s=Plant`, und zwar in beiden Richtungen. So löschen Sie nur die Organizes-Verweise in einer bestimmten Richtung vom Quell- zum Ziel-Node:

```csharp
client.DeleteReference(
        nodeId: "ns=2;s=Machines/MAC03",
        targetNodeId: "ns=2;s=Plant",
        direction: OpcReferenceDirection.ChildToParent);

```

```vbnet
client.DeleteReference( _
        nodeId:="ns=2;s=Machines/MAC03", _
        targetNodeId:="ns=2;s=Plant", _
        direction:=OpcReferenceDirection.ChildToParent)

```

Um Verweise eines anderen Typs als Organizes zu löschen, geben Sie den Typ über den zusätzlichen Parameter `referenceType` beziehungsweise `referenceTypeId` an:

```csharp
client.DeleteReference(
        nodeId: "ns=2;s=Machines/MAC03",
        targetNodeId: "ns=2;s=Plant",
        direction: OpcReferenceDirection.ChildToParent, 
        referenceType: OpcReferenceType.HierarchicalReferences);

```

```vbnet
client.DeleteReference( _
        nodeId:="ns=2;s=Machines/MAC03", _
        targetNodeId:="ns=2;s=Plant", _
        direction:=OpcReferenceDirection.ChildToParent, _
        referenceType:=OpcReferenceType.HierarchicalReferences)

```

So löschen Sie mehrere Verweise gleichzeitig:

```csharp
client.DeleteReferences(
        new OpcDeleteReference("ns=2;s=Machines/MAC01", "ns=2;s=Plant01"),
        new OpcDeleteReference("ns=2;s=Machines/MAC02", "ns=2;s=Plant01"),
        new OpcDeleteReference("ns=2;s=Machines/MAC03", "ns=2;s=Plant02"));

```

```vbnet
client.DeleteReferences( _
        New OpcDeleteReference("ns=2;s=Machines/MAC01", "ns=2;s=Plant01"), _
        New OpcDeleteReference("ns=2;s=Machines/MAC02", "ns=2;s=Plant01"), _
        New OpcDeleteReference("ns=2;s=Machines/MAC03", "ns=2;s=Plant02"))

```
