2014-06-22 7 views
9

Ich habe Probleme, mein Modell die Id -Eigenschaft einer Entität als Zeichenfolge darzustellen, aber es automatisch erstellt und intern von MongoDb als ein natives dargestellt.MongoDB C# -Treiber - Wie wird _id als ObjectId gespeichert, sondern der String-ID-Eigenschaft zugeordnet?

class Account 
{ 
    public string Id { get; set; } 
    ... 
} 

class AccountStore 
{ 
    static AccountStore() 
    { 
     BsonClassMap.RegisterClassMap<Account>(cm => 
     { 
      cm.AutoMap(); 
      cm.SetIgnoreExtraElements(true); 

      // map Id property here 
     }); 
    } 

    public void Save(Account account) 
    { 
     _accounts.Save(account); 
    } 
} 

Für die Linie // map Id property here in dem obigen Code, habe ich zahlreiche verschiedene Möglichkeiten zur Konfiguration des ID-Mapping und keine gearbeitet hat versucht. Die Art und Weise habe ich versucht, und die damit verbundenen Ausnahmen, die ausgelöst werden, wenn ich die Save Methode aufrufen, sind:

// Exception: No IdGenerator found. 
cm.IdMemberMap 
    .SetRepresentation(BsonType.ObjectId); 

// Exception: No IdGenerator found. 
cm.IdMemberMap 
    .SetRepresentation(BsonType.String); 

// Exception: Unable to cast object of type 'MongoDB.Bson.ObjectId' to type 'System.String'. 
cm.IdMemberMap 
    .SetRepresentation(BsonType.ObjectId) 
    .SetIdGenerator(ObjectIdGenerator.Instance); 

// Exception: Unable to cast object of type 'MongoDB.Bson.ObjectId' to type 'System.String'. 
cm.IdMemberMap 
    .SetRepresentation(BsonType.String) 
    .SetIdGenerator(ObjectIdGenerator.Instance); 

// Exception: Unable to cast object of type 'MongoDB.Bson.ObjectId' to type 'System.String'. 
cm.IdMemberMap 
    .SetIdGenerator(ObjectIdGenerator.Instance); 

Was mache ich falsch? Ich dachte, das wäre ein Standard-Anwendungsfall für das ID-Handling?

+0

Mögliche Duplikat [Wie BsonRepresentation Attribut durch Konvention anzuwenden, wenn MongoDB mit] (https://stackoverflow.com/questions/45043266/how-to- anwenden-bsonpräsentieren ation-attribute-by-convention-wenn-mit-mongodb) – dnickless

Antwort

9

Das hat sich geändert, ich benutze den neuesten 1.x-Treiber (Nuget-Paket <package id="mongocsharpdriver" version="2.0.0" targetFramework="net45" />) und statt setzen Sie den Serialisierer.

public class RegistrationAttempt 
{ 
    public string AttemptId { get; set; } 
} 

BsonClassMap.RegisterClassMap<RegistrationAttempt>(cm => 
{ 
    cm.AutoMap(); 
    cm.MapIdProperty(c => c.AttemptId) 
     .SetIdGenerator(StringObjectIdGenerator.Instance) 
     .SetSerializer(new StringSerializer(BsonType.ObjectId)); 
}); 
+0

@ Ich habe die Änderung zurückgesetzt, die die Versionsnummer des Treibers geändert hat. Obwohl das Paket 2.0.0 sagt, verwende ich den Legacy-Treiber, da der 2.0-Treiber die Unterstützung für IQueryable noch nicht hat. Das Paket "mongocsharpdriver" -Treiber zieht jedoch die neuesten Treiberpakete ein, so dass ich mich irren und eine Kombination von beiden verwenden könnte. Ich denke aber nicht, weil ich eine Warnung bekomme, dass ein Teil meines Codes eine veraltete API verwendet. – BenCr

+0

Danke, dieser Thread deckt jetzt beide Fälle ab! –

+0

Gott verdammt! Ich habe ObjectIdGenerator anstelle von StringObjectIdGenerator verwendet. Danke! Nur um hinzuzufügen, das funktioniert in der Version 2.4 des Treibers – Phil

5

die Antwort gefunden:

cm.IdMemberMap 
    .SetRepresentation(BsonType.ObjectId) 
    .SetIdGenerator(StringObjectIdGenerator.Instance); 

Dies ermöglicht es mir, als native ObjectId zu speichern und haben immer noch die Id als String in C# dargestellt.

public Account GetAccountById(string id) 
{ 
    return _accounts.FindOneById(ObjectId.Parse(id)); 
} 

bearbeiten Mai 2015 Scheinbar
der Fahrer, da ich diese Antwort geschrieben hat sich geändert: Als kleines gotcha, muss die ID vor abgefragten bei analysiert werden. Die andere Antwort ist für neuere Versionen korrekt, aber diese Antwort kann immer noch verwendet werden, wenn Sie eine ältere Version des Treibers verwenden.

+0

Ist das der 2.0-Treiber? Ich habe nicht die SetRepresentation-Funktion – BenCr

+0

Nicht sicher, aber es funktionierte vor einem Jahr ... –

+0

Nein, es ist jetzt geändert, ich werde eine aktuelle Antwort für die Menschen heute suchen. – BenCr

0

Falls Sie möchten, dass sehr gleiche Art von Mapping über eine ganze Reihe von Einrichtungen, ohne die Notwendigkeit, sich zu wiederholen, immer und immer wieder haben Sie vielleicht eine Konvention verwenden möchten:

public class 
StringObjectIdIdGeneratorConventionThatWorks : 
ConventionBase, IPostProcessingConvention 
{ 
    /// <summary> 
    /// Applies a post processing modification to the class map. 
    /// </summary> 
    /// <param name="classMap">The class map.</param> 
    public void PostProcess(BsonClassMap classMap) 
    { 
     var idMemberMap = classMap.IdMemberMap; 
     if (idMemberMap == null || idMemberMap.IdGenerator != null) 
      return; 
     if (idMemberMap.MemberType == typeof(string)) 
     { 
      idMemberMap.SetIdGenerator(StringObjectIdGenerator.Instance).SetSerializer(new StringSerializer(BsonType.ObjectId)); 
     } 
    } 
} 

.. .und verwenden sie es dann an die Stelle aller benutzerdefinierten Zuordnungen:

ConventionPack cp = new ConventionPack(); 
cp.Add(new StringObjectIdIdGeneratorConventionThatWorks()); 

ConventionRegistry.Register("TreatAllStringIdsProperly", cp, _ => true); 
Verwandte Themen