共用方式為


使用 WCF LOB 配接器 SDK 的開發最佳做法

您可以使用本主題中的最佳做法來改善應用程式和配接器。

在通道例外狀況關閉之前呼叫中止

當您撰寫使用 WCF 通道模型的應用程式時,應該先呼叫 IRequestChannel.Abort,然後才呼叫 ChannelFactory.Close。 如果沒有, ChannelFactory.Close 則會擲回例外狀況。

在下列範例中,嘗試在 try/catch 區塊(嘗試/捕捉區塊)內進行通道操作。 如果發生例外狀況,則會中止通道。

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.  
  }  
}  

同時實作異步和同步處理程式

可能的話,請在配接器中實作異步和同步處理程式。 如果您的配接器只實作同步呼叫,在處理大量訊息或多線程環境中使用配接器時,您可能會遇到封鎖問題。

使用連接共用

WCF LOB 配接器 SDK 預設支援連線共用。 不過,決定要將哪些連接共用屬性公開為系結屬性是由配接器開發人員決定的。 可用的連線集區設定定義在Microsoft.ServiceModel.Channels.Common.ConnectionPoolSettings中。

在使用配接器服務附件時,沒有選項以便輕鬆地將這些屬性揭露為配接器連線屬性。 配接器開發人員必須在配接器實作中手動定義屬性。

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

確定配接器支援 Two-Way 作業

如果您的配接器是從 BizTalk Server 呼叫,則它必須支援雙向作業,即使傳回值是 void 也一樣。 這是因為 BizTalk Server 預期任何傳出要求都會有回應,若您的配接器只支援單向操作,則會引發例外狀況。

以下是傳回 void 的要求-回應合約範例。

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

實施追蹤

在開發周期中,將追蹤功能加入到配接器中似乎不是很重要,這是因為您可以逐步執行程式碼並排除任何問題。 不過,在生產環境中安裝配接器之後,您可能無法使用運行時間偵錯來隔離問題。 如果您已在配接器中啟用追蹤,它可用來隔離發生失敗的位置。

如需進一步的詳細資訊,請參閱使用 WCF LOB 配接器 SDK 追蹤配接器

針對經常變更的設定使用 URI 屬性

決定是否要將自定義屬性公開為系結或 URI 屬性時,如果值經常變更,建議使用 URI 屬性。 系結屬性應該保留給很少變更的值。

範例系結屬性是所有連接所使用的資料庫伺服器名稱。 範例 URI 屬性是特定連接要使用的特定資料表或預存程式。

請勿在 URI 中傳遞使用者名稱或密碼值

如果您的配接器需要呼叫端的認證,建議使用 ClientCredentials 類別來擷取認證值,而不是在 URI 中傳遞客戶端認證。 ClientCredentials 類別是 WCF 的標準功能,旨在以更安全的方式將認證資訊從用戶端傳遞至服務。 將使用者信息當做 URI 字串的一部分傳遞,可能會在傳輸時公開用戶資訊。

下表顯示傳遞認證的建議方法。

方法 說明
設計時間 使用 [新增配接器服務參考外掛程式] 時,您可以指定配接器支援的客戶端認證類型。
執行時間 使用產生的 .NET CLR Proxy 時,您可以以程式設計方式設定客戶端認證。

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"); }

或者,如果您需要直接與通道互動,您可以使用 WCF 通道模型在建立通道處理站時指定客戶端認證。

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 組態 在用戶端組態檔中,新增 <endpointBehaviors> 元素,其中包含 <clientCredentials>。

<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>
使用 BizTalk 使用 WCF 配接器來取用您的配接器時,您可以在 [行為] 索引標籤上新增 clientCredentials 行為延伸模組。新增之後,您可以在端點行為中設定所需的用戶端憑證。

請勿同時傳回 StrongDataSetType 和 WeakDataSetType

如果您的配接器傳 DataSet回 ,請使用 Microsoft.ServiceModel.Channels.Common.QualifiedType.StrongDataSetType%2AMicrosoft.ServiceModel.Channels.Common.QualifiedType.WeakDataSetType%2A,但不同時使用兩者。 這兩種類型所產生的根節點名稱和命名空間完全相同,而且不能同時存在於 WSDL 中。

雖然 WeakDataSetTypeStrongDataSetType 都代表 System.Data.DataSetStrongDataSetType 但較容易在 .NET 應用程式中使用,因為產生的 Proxy 會顯示為 System.Data.Dataset。 所產生的 WeakDataSetType Proxy 是 XmlElement[],較難以在 .NET 應用程式中使用。 BizTalk Server 無法取用從 StrongDataSet傳回的架構,但能夠取用 WeakDataSetType

備註

StrongDataSetTypeWeakDataSetType 只會控制用戶端應用程式如何解譯配接器傳遞的 XML 訊息。 不論指定哪一種類型,XML 訊息都相同。

備註

StrongDataSetType回 時,您必須將 設定 Microsoft.ServiceModel.Channels.Common.MetadataSettings.CompileWsdl%2Afalse。 當設為true(預設值)時,會在配接器內呼叫XmlSchemaSet::Compile,以確保 WSDL 中沒有任何錯誤。不過,由StrongDataSetType生成的架構會在XmlSchemaSet中產生例外狀況。

將 設定 CompileWsdlfalse 略過配接器內的 WSDL 架構驗證,並在 Proxy 產生期間進行驗證。 svcutil.exe 等公用程式能夠為StrongDataSetTypeWeakDataSetType同時產生 Proxy。

若要同時使用 BizTalk 和 .NET 環境,請考慮實作系結屬性,以允許切換環境所指定的兩個傳回型別。

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

在 BizTalk Server 中建立有意義的 XSD 架構名稱

在使用 Consume Adapter Service BizTalk 專案附加元件的設計時工具時,XSD 架構名稱會在您的 BizTalk 專案中生成,該名稱是由 DefaultXsdFileNamePrefix 屬性、WSDL 中的 fileNameHint 註釋,以及必要時使用唯一的整數值來創建的。

例如,如果 DefaultXsdFileNamePrefix 設定為 「MyAdapter」,而且註釋設定為 「Stream」,則建立的 fileNameHint XSD 架構會命名為 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>  

備註

的預設值 DefaultXsdFileNamePrefix 是系結的名稱。 若要指定不同的值,請在 Adapter 類別中覆寫 DefaultXsdFileNamePrefix,該類別是從 Microsoft.ServiceModel.Channels.Common.AdapterBinding 衍生而來的。

有兩個可能的方法可將fileNameHint註解新增至架構:覆寫 OperationMetadata\TypeMetadata 中的 Export...Schema 方法,或覆寫匯接器的 IWsdlRetrieval 實作。 針對任一方法,您可以呼叫基底實作,然後將批注加入架構集合中的架構。

備註

覆寫 Export…Schema 方法時,相同架構中可能會有多個操作/類型定義,配接器應確定相同架構中多次出現的 fileNameHints 批註不會產生衝突。 「外掛程式取用配接器服務」若在架構中多次出現,將使用第一次出現的 fileNameHint

在下列範例中,IWsdlRetrieval 用於在 WSDL 中新增 fileNameHint 批註。

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

配接器應該只在配接器初始化期間設定 AdapterEnvironmentSettingsConnectionPoolManagerConnectionPoolCommonCacheSize ,而且不應該嘗試修改執行中實例的值。

如果目前正在執行的配接器實例上修改這些設定,這可能會導致新聯機覆寫目前執行連線的組態設定。

另請參閱

使用 WCF LOB 配接器 SDK 的開發最佳做法