共用方式為


使用 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 字串的一部分傳遞,可能會在傳輸時公開使用者資訊。

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

方法 Description
設計階段 使用 [新增配接器服務參考外掛程式] 時,您可以指定配接器支援的用戶端認證類型。
執行階段 使用產生的 .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 組態 在用戶端組態檔中,新增 < 包含 clientCredentials 的 endpointBehaviors > 元素 >< 。

<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 之類的公用程式能夠同時產生 和 WeakDataSetTypeStrongDataSetType Proxy。

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

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

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

使用取用配接器服務 BizTalk 專案增益集設計階段工具時,會使用 DefaultXsdFileNamePrefix 屬性建立 BizTalk 專案中產生的 XSD 架構名稱、 fileNameHint WSDL 中的批註,並視需要建立唯一的整數值。

例如,如果 DefaultXsdFileNamePrefix 設定為 「MyAdapter」,而且 fileNameHint 注釋設定為 「Stream」,則建立的 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 預設值是系結的名稱。 若要指定不同的值,請在衍生自 Microsoft.ServiceModel.Channels.Common.AdapterBinding 的 Adapter 類別中覆寫 DefaultXsdFileNamePrefix

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

注意

覆寫匯出時...架構方法,相同架構中可能會有多個作業/類型定義;配接器應該確定相同架構中出現多個 fileNameHints 批註不會衝突。 取用配接器服務增益集會在架構內多次發生時,使用 的第 fileNameHint 一次。

在下列範例中,IWsdlRetrieval 是用來將批註新增 fileNameHint 至 WSDL。

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 的開發最佳做法