2016-05-06 5 views
2

Ich habe folgendes abgespeckte DTO:Warum ist WCF/Mongo Ausnahme werfen: Ein Element mit demselben Schlüssel wurde bereits hinzugefügt

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

... und die folgende abgespeckte Mongo Service-Definition:

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

ich habe dann eine Client-Bibliothek, die einen WCF-Dienst Bezug auf MongoChartServiceChartServiceClient benannt hat.

Wenn ich eine Instanz von MongoChartService direkt erstellen und eine Instanz ChartDefinitionBase (vollständig implementiert und keine untergeordneten Klassen) injizieren, kann ich einen Rundgang in die Datenbank (Erstellen, Lesen, Löschen) durchführen. Wenn ich eine Instanz von ChartServiceClient erstelle und versuche, die gleichen Schritte mit dem abgespeckten DTO zu wiederholen, bekomme ich eine ServiceModel.FaultException, wenn GetAllCharts aufgerufen wird, mit ExceptionDetail "Ein Element mit dem gleichen Schlüssel wurde bereits hinzugefügt." Hier ist ein Beispiel für einen Komponententest mit Kommentaren.

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

Der Stack-Trace ist wie folgt:

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() 

Edit: Beachten Sie, dass die Ausnahme mit dem Aufruf von BsonClassMap.RegisterClassMap aufzutreten scheint. Diese Methode scheint sowohl mit Create als auch GetAllCharts() aufgerufen zu werden.

Jeder hat eine Idee, was los ist und wie Sie dieses Problem beheben können?

Antwort

1

Das Problem scheint aufgrund der Platzierung des Aufrufs BsonClassMap.RegisterClassMap im Konstruktor MongoChartService zu sein. Wenn Sie MongoChartService direkt verwenden, wird der Konstruktor nur einmal aufgerufen. Bei Verwendung von ChartServiceClient wird der MongoChartService-Konstruktor einmal auf Create und einmal auf GetAllCharts aufgerufen; Da jedoch ChartDefinitionBase das erste Mal registriert wurde, erzeugt der zweite Versuch, es zu registrieren, die Ausnahme.

die Probleme lösen, wenn entweder ich BsonIdAttribute auf Id verwenden oder den Anruf an BsonClassMap.RegisterClassMap an anderer Stelle, zum Beispiel über den Aufruf an den Client verschieben:

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

Die MongoDb documentation Staaten etwas zu diesem Effekt, obwohl ich ‚hadn t geschätzt, dass das Service-Konstruktor mehrmals aufgerufen werden würde:

Es ist sehr wichtig, dass die Registrierung von Klassenzuordnungen vor ihnen auftritt gebraucht zu werden. Der beste Ort, um sie zu registrieren, ist die App Start vor dem Initialisieren einer Verbindung mit MongoDB.

Verwandte Themen