Freigeben über


Bewährte Methoden für die Entwicklung mit dem WCF LOB Adapter SDK

Sie können die bewährten Methoden in diesem Thema verwenden, um Ihre Anwendungen und Adapter zu verbessern.

Aufrufen von Abbruch vor dem Schließen bei Kanal-Ausnahme

Wenn Sie eine Anwendung schreiben, die das WCF-Kanalmodell verwendet, sollten Sie aufrufen IRequestChannel.Abort , bevor Sie aufrufen ChannelFactory.Close. Wenn sie dies nicht tun, ChannelFactory.Close löst eine Ausnahme aus.

Im folgenden Beispiel werden Kanalvorgänge innerhalb eines try/catch-Blocks versucht. Wenn eine Ausnahme auftritt, wird der Kanal abgebrochen.

ChannelFactory<IRequestChannel> cf = new  ChannelFactory<IRequestChannel>();  
IRequestChannel channel = null;  
try  
{  
  cf.Open();  
  channel = cf.CreateChannel();  
  channel.Open();  
  channel.Request();// This causes the channel to go into a faulted state.  
  channel.Close();  
}  
catch (Exception e)  
{  
  // Abort the channel if we have one  
  if(channel != null)  
    channel.Abort();  
}  
finally  
{  
  if (cf.State == CommunicationState.Opened)  
  {  
    cf.Close(); // It throws an exception that the channel is in a faulted state.  
  }  
}  

Implementieren von asynchronen und synchronen Handlern

Implementieren Sie nach Möglichkeit sowohl asynchrone als auch synchrone Handler in Ihrem Adapter. Wenn Ihr Adapter nur synchrone Aufrufe implementiert, können Probleme beim Verarbeiten einer großen Anzahl von Nachrichten oder bei verwendung des Adapters in einer Multithreadumgebung auftreten.

Verwenden des Verbindungspoolings

Das WCF LOB Adapter SDK unterstützt standardmäßig Verbindungspooling. Es liegt jedoch beim Adapterentwickler, zu bestimmen, welche Verbindungspoolingeigenschaften als Bindungseigenschaften verfügbar gemacht werden sollen. Die verfügbaren Verbindungspooleinstellungen werden in Microsoft.ServiceModel.Channels.Common.ConnectionPoolSettingsdefiniert.

Es gibt keine Optionen im Add-In Adapterdienst nutzen, um diese Eigenschaften einfach als Adapterverbindungseigenschaften verfügbar zu machen. Der Adapterentwickler muss die Eigenschaften in der Adapterimplementierung manuell definieren.

public CustomAdapter(): base()  
{  
   this.Settings.ConnectionPool.EnablePooling = true;  
   this.Settings.ConnectionPool.HandlersShareSameConnection = true;  
   this.Settings.ConnectionPool.MaxConnectionsPerSystem = 50;  
   this.Settings.ConnectionPool.MaxAvailableConnections = 5;  
}  

Stellen Sie sicher, dass der Adapter Two-Way-Vorgänge unterstützt.

Wenn Der Adapter von BizTalk Server aufgerufen wird, muss er bidirektionale Vorgänge unterstützen, auch wenn der Rückgabewert void ist. Dies liegt daran, dass BizTalk Server eine Antwort erwartet, die von jeder ausgehenden Anforderung zurückgegeben wird, und eine Ausnahme auslöst, wenn Ihr Adapter nur unidirektionale Vorgänge implementiert.

Hier sehen Sie ein Beispiel für einen Anforderung/Antwort-Vertrag, der void zurückgibt.

[ServiceContract(Namespace=”Http:Microsoft.BizTalk.Samples.WCFAdapterSample”)]  
public interface ICalculator  
{  
   [OperationContract]  
   void Add(double n1, double n2);  
}  

Implementieren der Ablaufverfolgung

Während des Entwicklungszyklus erscheint es möglicherweise nicht wichtig, Ihrem Adapter die Ablaufverfolgung hinzuzufügen, da Sie den Code schrittweise durchlaufen und Probleme debuggen können. Sobald der Adapter jedoch in einer Produktionsumgebung installiert ist, können Sie möglicherweise nicht mehr das Laufzeitdebuggen verwenden, um Probleme zu isolieren. Wenn Sie die Ablaufverfolgung im gesamten Adapter aktiviert haben, kann sie verwendet werden, um zu isolieren, wo Fehler auftreten.

Weitere Informationen finden Sie unter Nachverfolgen eines Adapters mit dem WCF LOB Adapter SDK .

Verwenden von URI-Eigenschaften für häufig geänderte Einstellungen

Bei der Entscheidung, ob eine benutzerdefinierte Eigenschaft als Bindungs- oder URI-Eigenschaft verfügbar gemacht werden soll, empfiehlt es sich, eine URI-Eigenschaft zu verwenden, wenn sich der Wert häufig ändert. Bindungseigenschaften sollten für Werte reserviert sein, die sich selten ändern.

Eine Beispielbindungseigenschaft wäre ein Datenbankservername, der von allen Verbindungen verwendet wird. Eine Beispiel-URI-Eigenschaft wäre eine bestimmte Tabelle oder gespeicherte Prozedur, die von dieser bestimmten Verbindung verwendet werden soll.

Benutzernamen- oder Kennwortwerte im URI nicht übergeben

Wenn Ihr Adapter die Anmeldeinformationen des Aufrufers erfordert, wird empfohlen, die ClientCredentials-Klasse zum Abrufen von Anmeldeinformationen zu verwenden, anstatt Clientanmeldeinformationen als Teil des URI zu übergeben. Die ClientCredentials-Klasse ist ein Standardfeature von WCF, das anmeldeinformationen vom Client an den Dienst auf sicherere Weise übergeben soll. Die Übergabe der Benutzerinformationen als Teil der URI-Zeichenfolge kann die Benutzerinformationen während der Übertragung verfügbar machen.

Die empfohlenen Methoden zum Übergeben von Anmeldeinformationen sind in der folgenden Tabelle aufgeführt.

Methode BESCHREIBUNG
Entwurfszeit Wenn Sie das Add Adapter Service Reference Plug-In verwenden, können Sie die Clientanmeldeinformationstypen angeben, die der Adapter unterstützt.
Laufzeit Wenn Sie einen generierten .NET CLR-Proxy verwenden, können Sie die Clientanmeldeinformationen programmgesteuert festlegen.

static void Main(string[] args) { EchoServiceClient client = new EchoServiceClient(); client.ClientCredentials.UserName.UserName = "TestUser"; client.ClientCredentials.UserName.Password = "TestPassword"; string response=client.EchoString("Test String"); }

Wenn Sie direkt mit dem Kanal interagieren müssen, können Sie alternativ das WCF-Kanalmodell verwenden, um die Clientanmeldeinformationen beim Erstellen einer Kanalfactory anzugeben.

EchoAdapterBinding binding = new EchoAdapterBinding(); binding.Count = 3; ClientCredentials clientCredentials = new ClientCredentials(); clientCredentials.UserName.UserName = "TestUser"; clientCredentials.UserName.Password = "TestPassword"; BindingParameterCollection bindingParms = new BindingParameterCollection(); bindingParms.Add(clientCredentials); EndpointAddress address = new EndpointAddress("echo://"); IChannelFactory<IRequestChannel> requestChannelFactory = binding.BuildChannelFactory<IRequestChannel>(bindingParms); requestChannelFactory.Open();
WCF-Konfiguration Fügen Sie in der Clientkonfigurationsdatei ein <endpointBehaviors-Element> hinzu, das clientCredentials> enthält<.

<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0"> <system.serviceModel> . . . . . <behaviors> <endpointBehaviors> <behavior name="clientEndpointCredential"> <clientCredentials> <windows allowNtlm="false" allowedImpersonationLevel="Delegation" /> </clientCredentials> </behavior> </endpointBehaviors> </behaviors> </system.serviceModel> </configuration>
Verwenden von BizTalk Wenn Sie den WCF-Adapter verwenden, um Ihren Adapter zu nutzen, können Sie die Verhaltenserweiterung clientCredentials auf der Registerkarte Verhalten hinzufügen. Nachdem dies hinzugefügt wurde, können Sie die gewünschten Clientanmeldeinformationen im Endpunktverhalten festlegen.

Geben Sie nicht sowohl StrongDataSetType als auch WeakDataSetType zurück.

Wenn der Adapter einen DataSetzurückgibt, verwenden Sie entweder Microsoft.ServiceModel.Channels.Common.QualifiedType.StrongDataSetType%2A oder Microsoft.ServiceModel.Channels.Common.QualifiedType.WeakDataSetType%2A, aber nicht beide gleichzeitig. Der Name des Stammknotens und der Namespace, die von beiden Typen erstellt werden, sind identisch und können nicht gleichzeitig in einer WSDL vorhanden sein.

Während WeakDataSetType und StrongDataSetType beide ein System.Data.DataSetdarstellen, StrongDataSetType ist einfacher in .NET-Anwendungen zu verwenden, da der generierte Proxy als System.Data.Datasetangezeigt wird. Der von WeakDataSetType generierte Proxy ist XmlElement[], was in einer .NET-Anwendung schwieriger zu verwenden ist. BizTalk Server kann das von StrongDataSetzurückgegebene Schema nicht nutzen, kann aber nutzenWeakDataSetType.

Hinweis

StrongDataSetType und WeakDataSetType steuern nur, wie die Clientanwendung die vom Adapter übergebenen XML-Nachrichten interpretiert. Die XML-Nachricht ist unabhängig davon, welcher Typ angegeben wird, identisch.

Hinweis

Wenn Sie zurückgebenStrongDataSetType, müssen Sie auf falsefestlegenMicrosoft.ServiceModel.Channels.Common.MetadataSettings.CompileWsdl%2A. Bei Festlegung auf truewird der Standardwert innerhalb des Adapters aufgerufen, um sicherzustellen, XmlSchemaSet::Compile dass keine Fehler in der WSDL vorliegen. Das von erzeugte StrongDataSetType Schema generiert jedoch eine Ausnahme in XmlSchemaSet.

Wenn Sie CompileWsdl auf festlegen, false wird die WSDL-Schemavalidierung innerhalb des Adapters umgangen, und die Überprüfung erfolgt während der Proxygenerierung. Hilfsprogramme wie svcutil.exe können einen Proxy sowohl für als auch StrongDataSetTypeWeakDataSetTypegenerieren.

Um sowohl mit BizTalk- als auch mit .NET-Umgebungen zu arbeiten, sollten Sie eine Bindungseigenschaft implementieren, die den Wechsel zwischen den beiden Rückgabetypen ermöglicht, wie von der Umgebung vorgegeben.

internal static QualifiedType GetDataSetQualifiedType(MyAdapterBindingProperties bindingProperties)  
{  
   if (bindingProperties.EnableBizTalkCompatibility)  
      return QualifiedType.WeakDataSetType;  
   else  
      return QualifiedType.StrongDataSetType;  
}  

Erstellen aussagekräftiger XSD-Schemanamen in BizTalk Server

Wenn Sie das Add-In -Add-In des Verbrauchsadapterdiensts verwenden, wird der Name des in Ihrem BizTalk-Projekt generierten XSD-Schemas mithilfe der DefaultXsdFileNamePrefix -Eigenschaft, der fileNameHint Anmerkung in der WSDL und, falls erforderlich, einem eindeutigen ganzzahligen Wert erstellt.

Wenn DefaultXsdFileNamePrefix beispielsweise auf "MyAdapter" und die fileNameHint Anmerkung auf "Stream" festgelegt ist, heißt das erstellte XSD-Schema MyAdapterStream.xsd.

<xs:schema elementFormDefault='qualified' targetNamespace='http://schemas.microsoft.com/Message' xmlns:xs='http://www.w3.org/2001/XMLSchema' xmlns:tns='http://schemas.microsoft.com/Message'>  
<xs:annotation>  
<xs:appinfo>  
<fileNameHint xmlns='http://schemas.microsoft.com/servicemodel/adapters/metadata/xsd'>Stream</fileNameHint>  
</xs:appinfo>  
</xs:annotation>  
<xs:simpleType name='StreamBody'>  
<xs:restriction base='xs:base64Binary' />  
</xs:simpleType>  
</xs:schema>  

Hinweis

Der Standardwert von DefaultXsdFileNamePrefix ist der Name Ihrer Bindung. Um einen anderen Wert anzugeben, überschreiben Sie DefaultXsdFileNamePrefix in Ihrer Adapterklasse, die von Microsoft.ServiceModel.Channels.Common.AdapterBindingabgeleitet wird.

Es gibt zwei mögliche Methoden zum Hinzufügen der fileNameHint Anmerkung zum Schema: Überschreiben sie den Export... Schemamethoden für OperationMetadata\TypeMetadata oder überschreiben die IWsdlRetrieval-Implementierung des Adapters. Für beide Methoden können Sie die Basisimplementierung aufrufen und dann die Anmerkung den Schemas in der Schemaauflistung hinzufügen.

Hinweis

Beim Überschreiben von Export... Schemamethoden, es können mehrere Vorgangs-/Typdefinitionen im selben Schema vorhanden sein. Der Adapter sollte sicherstellen, dass mehrere Vorkommen der fileNameHints Anmerkung im selben Schema nicht in Konflikt geraten. Das Add-In Adapter-Dienst nutzen verwendet das erste Vorkommen von, fileNameHint wenn es innerhalb eines Schemas mehrmals auftritt.

Im folgenden Beispiel wird IWsdlRetrieval verwendet, um die fileNameHint Anmerkung zur WSDL hinzuzufügen.

sealed class MyAdapterWsdlRetrieval : IWsdlRetrieval  
{  
   IWsdlRetrieval mBaseWsdlRetrieval;  
   public MyAdapterWsdlRetrieval(IWsdlRetrieval baseWsdlRetrieval)  
   {  
      mBaseWsdlRetrieval = baseWsdlRetrieval;  
   }  

   ServiceDescription IWsdlRetrieval.GetWsdl(Microsoft.ServiceModel.Channels.MetadataRetrievalNode[] nodes, Uri uri, TimeSpan timeout)  
   {  
      ServiceDescription baseDesc = mBaseWsdlRetrieval.GetWsdl(nodes, uri, timeout);  
      foreach (XmlSchema schema in baseDesc.Types.Schemas)  
      {  
         CreateFileNameHint(schema);  
      }  
      return baseDesc;  
   }  

   void CreateFileNameHint(XmlSchema schema)  
   {  
      string targetNamespace = schema.TargetNamespace;  
      if (string.IsNullOrEmpty(targetNamespace))  
         return;  
      string fileNameHint = null;  
      //determine the filename based on namespace  
      if (targetNamespace.StartsWith("myadapter:// adapters.samples.myadaptpter/HelloWorld"))  
      {  
         fileNameHint = "HelloWorld";  
      }  
      if (targetNamespace.StartsWith("myadapter:// adapters.samples.myadapter/Hello"))  
      {  
         fileNameHint = "Hello";  
      }  
      //create the annotation and populate it with fileNameHint  
      XmlSchemaAnnotation annotation = new XmlSchemaAnnotation();  
      XmlSchemaAppInfo appInfo = new XmlSchemaAppInfo();  
      XmlDocument doc = new XmlDocument();  
      XmlNode[] fileNameHintNodes = new XmlNode[1];  
      fileNameHintNodes[0] = doc.CreateElement(null, "fileNameHint", "http://schemas.microsoft.com/servicemodel/adapters/metadata/xsd");  
      fileNameHintNodes[0].AppendChild(doc.CreateTextNode(fileNameHint));  
      appInfo.Markup = fileNameHintNodes;  
      annotation.Items.Add(appInfo);  
      schema.Items.Insert(0, annotation);  
   }  

AdapterEnvironmentSettings während der Verarbeitung nicht ändern

Der Adapter sollte während der Adapterinitialisierung nur adapterEnvironmentSettings, ConnectionPoolManager, ConnectionPool und CommonCacheSize festlegen und nicht versuchen, die Werte für eine ausgeführte instance zu ändern.

Wenn diese Einstellungen auf einem derzeit ausgeführten Adapter instance geändert werden, kann dies dazu führen, dass neue Verbindungen Konfigurationseinstellungen für derzeit ausgeführte Verbindungen überschreiben.

Weitere Informationen

Bewährte Methoden für die Entwicklung mit dem WCF LOB Adapter SDK