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 にユーザー名またはパスワードの値を渡さない
アダプターで呼び出し元の資格情報が必要な場合は、クライアント資格情報を URI の一部として渡す代わりに、 ClientCredentials クラスを使用して資格情報の値を取得することをお勧めします。 ClientCredentials クラスは、より安全な方法でクライアントからサービスに資格情報を渡すことを目的とした WCF の標準機能です。 URI 文字列の一部としてユーザー情報を渡すと、転送中にユーザー情報が公開される可能性があります。
資格情報を渡すための推奨される方法を次の表に示します。
メソッド | 説明 |
---|---|
設計時 | アダプター サービス参照の追加プラグインを使用する場合は、アダプターがサポートするクライアント資格情報の種類を指定できます。 |
実行時 | 生成された .NET CLR プロキシを使用する場合は、クライアント資格情報をプログラムで設定できます。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.WeakDataSetType%2A
のいずれかをMicrosoft.ServiceModel.Channels.Common.QualifiedType.StrongDataSetType%2A
使用しますが、両方を同時に使用しないでください。 両方の型によって生成されるルート ノード名と名前空間は同一であり、WSDL 内に同時に存在することはできません。
WeakDataSetType
と StrongDataSetType
の両方が をSystem.Data.DataSet
StrongDataSetType
表しますが、生成されたプロキシは としてSystem.Data.Dataset
表示されるため、.NET アプリケーションで使用する方が簡単です。 によって WeakDataSetType
生成されるプロキシは です XmlElement[]
。これは、.NET アプリケーションで使用するのがより困難です。 BizTalk ServerからStrongDataSet
返されたスキーマを使用できませんが、 を使用WeakDataSetType
できます。
Note
StrongDataSetType
と は、 WeakDataSetType
クライアント アプリケーションがアダプターによって渡される XML メッセージを解釈する方法のみを制御します。 XML メッセージは、指定された型に関係なく同じです。
Note
を返すときは StrongDataSetType
、 を に設定 Microsoft.ServiceModel.Channels.Common.MetadataSettings.CompileWsdl%2A
する false
必要があります。 に true
設定すると、 XmlSchemaSet::Compile
既定の がアダプター内で呼び出され、WSDL にエラーが発生しないようにしますが、 によって StrongDataSetType
生成されるスキーマでは で XmlSchemaSet
例外が生成されます。
を に設定 CompileWsdl
すると false
、アダプター内で WSDL スキーマの検証がバイパスされ、検証はプロキシの生成中に行われます。 svcutil.exe などのユーティリティは、 と WeakDataSetType
の両方StrongDataSetType
のプロキシを生成できます。
BizTalk 環境と .NET 環境の両方を操作するには、環境で指示されている 2 つの戻り値の型を切り替えるバインディング プロパティを実装することを検討してください。
internal static QualifiedType GetDataSetQualifiedType(MyAdapterBindingProperties bindingProperties)
{
if (bindingProperties.EnableBizTalkCompatibility)
return QualifiedType.WeakDataSetType;
else
return QualifiedType.StrongDataSetType;
}
BizTalk Serverでわかりやすい XSD スキーマ名を作成する
アダプター サービス BizTalk プロジェクト アドインのデザイン時ツールを使用する場合、BizTalk プロジェクトで生成される XSD スキーマの名前は、 プロパティ、WSDL 内の注釈、fileNameHint
および必要に応じて一意の整数値を使用してDefaultXsdFileNamePrefix
作成されます。
たとえば、 が "MyAdapter" に設定されfileNameHint
、注釈が "Stream" に設定されている場合DefaultXsdFileNamePrefix
、作成される 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>
Note
の既定値 DefaultXsdFileNamePrefix
は、バインドの名前です。 別の値を指定するには、 からMicrosoft.ServiceModel.Channels.Common.AdapterBinding
派生した Adapter クラスで をオーバーライドDefaultXsdFileNamePrefix
します。
スキーマに注釈を追加 fileNameHint
するには、Export... をオーバーライドする方法が 2 つあります。OperationMetadata\TypeMetadata のスキーマ メソッド、またはアダプターの IWsdlRetrieval 実装をオーバーライドします。 どちらのメソッドでも、基本実装を呼び出し、スキーマ コレクション内のスキーマに注釈を追加できます。
Note
エクスポートをオーバーライドする場合...スキーマ メソッドでは、同じスキーマに複数の操作/型定義が存在する可能性があります。アダプターは、同じスキーマ内の注釈が 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 を変更しない
アダプターは、アダプターの初期化時にのみ AdapterEnvironmentSettings、 ConnectionPoolManager、 ConnectionPool、および CommonCacheSize を設定する必要があり、実行中のインスタンスの値の変更を試みてはなりません。
これらの設定が現在実行中のアダプター インスタンスで変更されると、現在実行中の接続の構成設定が新しい接続によって上書きされる可能性があります。