2010-12-07 24 views
5

Si j'ai une collection d'entreprise qui contient des divisions intégrées:Mise à jour d'un document intégré dans MongoDB avec pilote officiel C#

{ 
    "_id": 1 
    "_t": "Company", 
    "Name": "Test Company" 
    "Divisions": [ 
    { 
     "_id": 1 
     "_t": "Division", 
     "Name": "Test Division 1" 
    }, 
    { 
     "_id": 2 
     "_t": "Division", 
     "Name": "Test Division 2" 
    } 
    ] 
} 

Quelle est la meilleure façon de sauvegarder/mettre à jour une division entière lors de l'utilisation du official 10gen C# driver? (La dernière version 0.9.)

J'utilise Update.AddToSetWrapped pour ajouter des divisions, et cela fonctionne bien, mais j'aimerais aussi pouvoir mettre à jour des documents en fonction de leur _id.

Par exemple, si je définir la méthode de mise à jour suivante:

public void UpdateDivision(IDivision division) 
{ 
    var mongo = MongoServer.Create(_connectionString); 
    var database = mongo.GetDatabase(_databaseName); 
    var query = Query.EQ("_id", division.CompanyId); 
    var update = Update.AddToSetWrapped("Divisions", division); 
    database.GetCollection<Company>("Company") 
      .Update(query, update, UpdateFlags.Upsert, SafeMode.True); 
} 

et l'appeler comme ceci:

var division = GetDivisionById(1); 
division.Name = "New Name"; 
UpdateDivision(division); 

Ensuite, une nouvelle instance de la division sera ajoutée à l'ensemble, parce que même si le "_id" est toujours 1, le nom est différent, et donc c'est un document unique.

Alors, quel est le bon moyen de mettre à jour un document incorporé?

Jusqu'à ce que je viens avec une meilleure solution, je vais d'abord $pull la division originale, puis $addToSet avec la division modifiée. Cela fonctionne mais n'est évidemment pas idéal car il effectue deux mises à jour séparées.

Répondre

11

Vous pouvez utiliser la fonction de modification du tableau de position de MongoDB mettre à jour une division entière dans le tableau à la fois comme suit:

var division = GetDivisionById(1); 
division.Name = "New Name"; 
// change any other properties of division you want 
collection.Update(
    Query.EQ("Divisions._id", 1), 
    Update.Set("Divisions.$", BsonDocumentWrapper.Create<IDivision>(division)) 
); 

Les principales choses qui se passent ici sont:

  1. L'utilisation Depuis Update.Set
  2. Depuis Update.Set nécessite un BsonValue comme son deuxième argument, nous devons utiliser un BsonDocumentWrapper pour contenir la valeur de division (le paramètre de type IDivision à Create définit le nominalType à la sérialisation à IDivision qui entraîne l'écriture du discriminateur "_t").