2016-05-06 14 views
2

我有以下的簡裝DTO:爲什麼WCF /蒙戈拋出異常:具有相同鍵的項已被添加

[DataContract] 
public class ChartDefinitionBase 
{ 
    [DataMember] 
    public string Id { get; private set; } 
} 

...及以下簡裝蒙戈服務定義:

public class MongoChartService : IChartService 
{ 
    private readonly IMongoCollection<ChartDefinitionBase> _collection; 
    private const string _connectionStringKey = "MongoChartRepository"; 

    internal MongoChartService() 
    { 
     // Exception occurs here. 
     BsonClassMap.RegisterClassMap<ChartDefinitionBase>(cm => 
     { 
       cm.AutoMap(); 
       cm.MapIdMember(c => c.Id).SetIdGenerator(StringObjectIdGenerator.Instance); 
     }); 
     var connectionString = ConfigurationManager.ConnectionStrings[_connectionStringKey].ConnectionString; 
     var settings = MongoClientSettings.FromUrl(new MongoUrl(connectionString)); 
     var client = new MongoClient(settings); 
     var database = client.GetDatabase(ConfigurationManager.ConnectionStrings[_connectionStringKey].ProviderName); 
     _collection = database.GetCollection<ChartDefinitionBase>("Charts"); 
    } 

    public void Create(ChartDefinitionBase instance) 
    { 
     _collection.InsertOne(instance); 
    } 

    public IEnumerable<ChartDefinitionBase> GetAllCharts() 
    { 
     var charts = _collection.Find(_ => true).ToList(); 
     return charts; 
    } 
} 

然後我有其中有一個WCF服務引用MongoChartService名爲ChartServiceClient客戶端庫。

當我直接創建MongoChartService的實例並注入ChartDefinitionBase(完全實現且沒有子類)的實例時,我可以完成數據庫的往返(創建,讀取,刪除)。如果我創建了一個ChartServiceClient的實例並嘗試用精簡的DTO重複相同的步驟,當調用GetAllCharts時,我得到一個ServiceModel.FaultException,ExceptionDetail「具有相同密鑰的項目已被添加。」這是一個帶有註釋的示例單元測試。

[TestMethod, TestCategory("MongoService")] 
    public void ChartServiceClient_CRD_ExecutesSuccessfully() 
    { 
     SetupHost(); 
     using (var client = new ChartServiceClient()) 
     { 
      client.Create(_dto); // Create method succeeds. Single entry in dB with Mongo-generated ID. 
      ChartDefinitionBase dto = null; 
      while (dto == null) 
      { 
       var dtos = client.GetAllCharts(); // Exception occurs here. 
       dto = dtos.SingleOrDefault(d => d.Id == _dto.Id); 
      } 
      client.Delete(_dto); 
      while (dto != null) 
      { 
       var dtos = client.GetAllCharts(); 
       dto = dtos.SingleOrDefault(d => d.Id == _dto.Id); 
      } 
     } 
    } 

堆棧跟蹤如下:

Server stack trace: 
    at System.ServiceModel.Channels.ServiceChannel.ThrowIfFaultUnderstood(Message reply, MessageFault fault, String action, MessageVersion version, FaultConverter faultConverter) 
    at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc) 
    at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout) 
    at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation) 
    at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message) 

Exception rethrown at [0]: 
    at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) 
    at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) 
    at QRPad.Spc.DataLayer.Charts.Service.Client.ServiceReference.IChartService.GetAllCharts() 
    at QRPad.Spc.DataLayer.Charts.Service.Client.ServiceReference.ChartServiceClient.GetAllCharts() 

編輯:注意異常似乎與調用BsonClassMap.RegisterClassMap發生。這種方法似乎用CreateGetAllCharts()來調用。

任何人有任何想法是怎麼回事以及如何解決這個問題?

回答

1

這個問題似乎是由於在MongoChartService的構造函數中調用BsonClassMap.RegisterClassMap所致。直接使用MongoChartService時,構造函數只被調用一次。當使用ChartServiceClient時,MongoChartService構造函數在Create上調用一次,在GetAllCharts上調用一次;然而,由於ChartDefinitionBase是第一次註冊,第二次嘗試註冊會產生異常。

的問題解決了,當我要麼使用BsonIdAttributeId或呼叫轉移到BsonClassMap.RegisterClassMap其他地方,比如調用客戶端上面:

[TestMethod, TestCategory("MongoService")] 
public void ChartServiceClient_CRD_ExecutesSuccessfully() 
{ 
    SetupHost(); 
    BsonClassMap.RegisterClassMap<ChartDefinitionBase>(cm => 
    { 
     cm.AutoMap(); 
     cm.MapIdMember(c => c.Id).SetIdGenerator(StringObjectIdGenerator.Instance); 
    }); 
    using (var client = new ChartServiceClient()) 
    { 
     client.Create(_dto); 
     ChartDefinitionBase dto = null; 
     while (dto == null) 
     { 
      var dtos = client.GetAllCharts(); 
      dto = dtos.SingleOrDefault(d => d.Id == _dto.Id); 
     } 
     client.Delete(_dto); 
     while (dto != null) 
     { 
      var dtos = client.GetAllCharts(); 
      dto = dtos.SingleOrDefault(d => d.Id == _dto.Id); 
     } 
    } 
} 

MongoDb documentation狀態的東西這樣的效果,雖然我hadn」 t讚賞服務構造函數將被多次調用:

對於需要它們的類別映射的註冊先於 發生是非常重要的。註冊它們的最佳位置是在初始化與MongoDB的連接之前啓動的應用程序 。

相關問題