2012-05-29 47 views
5

這個問題是圍繞着如何構建WCF服務,使其隨着時間的推移而變得容易。 在不描述問題的情況下,很難獲得對此的響應深度。WCF體系結構和Evolution,版本

背景

我開發的WCF服務和客戶端的大系統。 服務器端很容易更新,因爲只有10臺服務器在運行該代碼。

儘管自動化程度很高,客戶仍然很難在300,000+ WCF客戶端進行更新,但更新總是需要一些時間,並且只能在兩到三週內獲得較高的更新成功率。

數據契約

[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是通過一系列的網絡服務非常普遍。

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)的一個組件,ServiceContract,並實現在自己的裝配結束了與DataContract

的客戶幾乎每個插件結束了一個非常難看,

MyWebService1.MyContract 
MyWebService2.MyContract 

隨着MyContractFactory的複製和粘貼。雖然DataContract是相同的,但客戶端不包含DataContract程序集這一事實意味着它出現在不同對象的不同名稱空間下。

實現2個

的客戶現在包括DataContract裝配,ServiceContracts是在一個單獨的裝配服務實現,客戶端可能包括一些ServiceContract組件是否會與代碼重用(不再拷貝援助和粘貼)。

問題

隨着第二執行我現在面臨的困難,我該如何更新我的DataContractServiceContracts

  1. 我是否更新相同的程序集並增加版本號?在所有客戶端升級時如何保持向後兼容性?打破客戶,直到他們更新是不可接受的。

  2. 我是否創建了一個新類,該類擴展了MyDataContract,在新的ServiceContract下接受新類型的新方法?這是否意味着我的合同的每一個小改動都需要一個新的程序集?在幾年的時間內,我會如何阻止它達到數百個?

  3. 其他一些解決方案?

無論我認爲通過什麼解決方案,他們都似乎有一個主要的缺點。

似乎沒有要(至少我)的,

  • 保留向後兼容,直到客戶更新
  • 保持客戶沒有膨脹修剪作爲軟件的發展隨着時間的推移
  • 沒有明顯污染我的ServiceContractOperationContract的過載需要一個新的「名稱」)。我已經有了像下面這樣的東西,它讓我覺得隨着時間的推移而噩夢。

經營合同的複雜性

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

及以下配置

<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

我最終使用我已下更新1中描述的方法。雖然WSDL看起來不正確,但是當我測試過這個服務時,該服務確實向下兼容老客戶端。

回答

5

微軟和大多數受尊重的WCF專家都可能會說同樣的事情:版本控制應該使用合同名稱空間來處理。

我不要吝嗇你的組件的.NET命名空間 - 我指的是實際的WCF服務(和數據合同)命名空間 - 所以你應該有:

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

什麼等等 - 有些人喜歡通過一年的版本/月:

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

這可以讓你有相同服務的多個版本,只要客戶來使用舊版本(由服務命名空間表示)打電話,他們會得到舊版本(只要你仍然公開)。

請參見:

+0

@馬克-S一些偉大的答案在這些鏈接,謝謝!仍然消化它們 –

+0

@ marc-s似乎你不能保留相同的合約名稱? –

+1

@MAfifi:不 - 你也不應該!這是一個基本原則,像服務合同這樣的界面是**不可變的** - 如果你需要添加一些東西給它,你需要給它一個新的名字。當然,你應該**永遠不會**通過改變例如打破現有界面。參數的數量或數據類型... –