2012-05-29 13 views
5

この質問は、時間の経過とともに進化しやすくするためのWCFサービスの設計方法に関するものです。 問題を説明することなくこれに対する応答の深さを得ることは困難です。WCF Architecture、およびバージョン

背景

私は、WCFサービスとクライアントの大規模なシステムを開発しています。 このコードを実行しているサーバーが10台しかないため、サーバー側の更新は簡単です。

高度な自動化にもかかわらず、クライアントは30万人以上のWCFクライアントで更新するのが非常に難しく、更新には常に時間がかかり、2〜3週間にわたって高い更新成功率しか達成できません。

データは

[DataContract] 
public class MyContract 
{ 
    [DataMember] 
    public int Identity {get; set;} 

    [DataMember] 
    public string Name {get; set;} 

    // More members 
} 

DataContractを初期化することは困難である契約やお使いのマシンのための適切なインスタンスを取得初期化するための標準的なMyContractFactoryクラスを持っています。

public class static MyContractFactory 
{ 
    public static MyContract GetMyContract() 
    { 
     // Complex implementation 
    } 
} 

ServiceContracts

DataContractは、Webサービスの範囲全体で非常に一般的です。

namespace MyPrefix.WebServicve1 
{ 
    [ServiceContract] 
    public class IMyInterface1 
    { 
     [OperationContract] 
     public void DoSomethingWithMyContract(MyContract data); 
    } 

    [ServiceContract] 
    public class IMyInterface2 
    { 
     [OperationContract] 
     public void DoSomethingDifferentWithMyContract(MyContract data); 
    } 
} 

クライアント

私のクライアントは、私たちがそのプラグインを持っている信頼のレベルに応じて、個別のプロセスやアプリケーションドメインのいずれかで実行されているプラ​​グインを使用してベースのプラグインです。

実装1

この(デフォルトWCF)の私の最初の実装は、独自のアセンブリ内の1つのアセンブリ、ServiceContract、および実装にDataContractになってしまいました。

クライアントは、ほぼすべてのプラグインでMyContractFactoryのコピー&ペーストして、非常に醜い、

MyWebService1.MyContract 
MyWebService2.MyContract 

になってしまいました。 DataContractは同じですが、クライアントにはDataContractアセンブリが含まれていなかったため、異なるオブジェクトとして異なる名前空間に表示されました。

実装2つの

クライアントが今DataContractアセンブリを含む、ServiceContractsは、サービスの実装に別のアセンブリであり、それはコードの再利用(これ以上のコピーに役立つ場合、クライアントはServiceContractアセンブリの一部を含むことができペースト)。私は今の困難に直面しています第2の実施と

質問

、どのように私は私のDataContractServiceContractsを更新していますか?

  1. 同じアセンブリを更新してバージョン番号を増やしますか?すべてのクライアントのアップグレード中に、下位互換性を維持するにはどうすればよいですか?更新するまでクライアントを壊すことは受け入れられません。

  2. MyDataContractのクラスを拡張した新しいアセンブリを作成しますか?新しいタイプを新しいServiceContractの下で受け入れる新しいメソッドを作成しますか?それは新しい契約が必要な私の契約のすべてのマイナーチェンジに当てはまりますか?数年後に文字通り数百になるのをやめさせるにはどうすればいいですか?

  3. その他の解決策はありますか?

私が考えている解決法にかかわらず、すべてに大きな欠点があるようです。ソフトウェアは

  • 時間をかけて進化すると、クライアントは、クライアントを維持
  • を更新するまで、下位互換性を保全

    、の(少なくとも私には)があるようには思えない
    • はありません肥大化とトリム私のServiceContractをあまり汚染しないでください(OperationContractの過負荷は新しい「名前」を必要とします)。私はすでに以下のようなものを持っています。そして、それは私を時間をかけて維持する悪夢に襲われます。

    運用契約の複雑

    [OperationContract] 
    public void DoSomethingWithMyContract(MyContract data); 
    
    [OperationContract(Name = "DoSomethingWithMyDataByAdditionalData"] 
    public void DoSomethingWithMyContract(MyContract data, MyContract2 additionalData); 
    

    私は、大規模環境で時間をかけて取り組んできました解決策を探しています。ブログのエントリなどは大歓迎です。

    アップデート1

    「スキーマレス」の変更を使用しての限界を見るとは、異なる名前空間は必ず方法のように思えます。しかし、期待通りには機能していない。

    [ServiceContract(
        Name = "IServiceContract", 
        Namespace = "http://myurl/2012/05")] 
    public interface IServiceContract1 
    { 
        // Some operations 
    } 
    
    [ServiceContract(
        Name = "IServiceContract", 
        Namespace = "http://myurl/2012/06")] 
    public interface IServiceContract2 
    { 
        // Some different operations using new DataContracts 
    } 
    
    次のサービスで

    public class MyService : IServiceContract1, IServiceContract2 
    { 
        // Implement both operations 
    } 
    

    と、次の設定2つの異なる名前を持つ2つの契約で

    <service behaviorConfiguration="WcfServiceTests.ServiceBehavior" 
        name="Test.MyService"> 
        <endpoint 
         address="2012/05" 
         binding="wsHttpBinding" 
         contract="Test.IServiceContract1"> 
         <identity> 
         <dns value="localhost" /> 
         </identity> 
        </endpoint> 
        <endpoint 
         address="2012/06" 
         binding="wsHttpBinding" 
         contract="Test.IServiceContract2"> 
         <identity> 
         <dns value="localhost" /> 
         </identity> 
        </endpoint> 
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> 
        </service> 
    

    結果の下に、私は

    、私が私のクライアントを指すことができることを期待しました

    http://myurl.com/MyService.svc/2012/05旧バージョンの場合はhttp://myurl.com/MyService.svc/2012/06

    しかし、ServiceContractの名前を保持したいのであれば、同じサービスの別々のエンドポイントアドレスではなく、2つの別々のサービスである必要がありますか?

    アップデート2

    私は更新1で説明している方法を使用して終了。 WSDLは間違っていますが、これをテストしたときに古いクライアントの下位互換性があります。

  • 答えて

    5

    マイクロソフトと尊敬されているWCF指導者のほとんどは、おそらく同じことを言うでしょう。バージョン管理は、名前空間を使用して処理する必要があります。

    私はあなたのアセンブリの.NET名前空間を意味するものではありません - 名前空間私は、実際のWCFサービス(およびデータコントラクト)を意味 - あなたは持っている必要があります。

    [ServiceContract(Namespace="http://services.yourcompany.com/Service1/V01"] 
    

    か何かのような - のような一部の人々

    [ServiceContract(Namespace="http://services.yourcompany.com/Service1/2012/05"] 
    

    これは、あなたが同じサービスの複数のバージョンを持つことができ、そして限り、クライアントが(サービスの名前空間によって示される)古いバージョンで呼び出す来るように、彼らが得るだろう:年/月ごとのバージョンに古いバージョン(あなたがまだそれを公開している限り)。

    参照:これらのリンクでMARC-sのいくつかの素晴らしい答え@

    +0

    、ありがとう! –

    +0

    @ marc-sあなたは同じ契約名を保持できるようには思われません。 –

    +1

    @MAfifi:いいえ - どちらもお勧めしません!サービス契約のようなインターフェースは**不変です** - 何かを追加する必要がある場合は、新しい名前を付ける必要があります。もちろん、既存のインターフェースを破ることは決してありません。パラメータの数やデータ型... –

    関連する問題