public static ToDotPath ( IEnumerable | ||
keys | IEnumerable | |
return | string |
public async Task <TrackableDictionary <TKey, TValue> > LoadAsync(IMongoCollection <BsonDocument> collection, params object[] keyValues) { if (keyValues.Length == 0) { throw new ArgumentException("At least 1 keyValue required."); } BsonDocument doc; if (keyValues.Length == 1) { doc = await collection.Find(Builders <BsonDocument> .Filter.Eq("_id", keyValues[0])).FirstOrDefaultAsync(); } else { // partial query var partialKeys = keyValues.Skip(1); var partialPath = DocumentHelper.ToDotPath(partialKeys); var partialDoc = await collection.Find(Builders <BsonDocument> .Filter.Eq("_id", keyValues[0])) .Project(Builders <BsonDocument> .Projection.Include(partialPath)) .FirstOrDefaultAsync(); doc = DocumentHelper.QueryValue(partialDoc, partialKeys) as BsonDocument; } if (doc == null) { return(null); } return(ConvertToTrackableDictionary(doc)); }
public async Task <TrackableList <T> > LoadAsync(IMongoCollection <BsonDocument> collection, params object[] keyValues) { if (keyValues.Length < 2) { throw new ArgumentException("At least 2 keyValue required."); } // partial query var keyPath = keyValues.Length > 1 ? DocumentHelper.ToDotPath(keyValues.Skip(1)) : ""; var partialDoc = await collection.Find(Builders <BsonDocument> .Filter.Eq("_id", keyValues[0])) .Project(Builders <BsonDocument> .Projection.Include(keyPath)) .FirstOrDefaultAsync(); if (partialDoc == null) { return(null); } var doc = DocumentHelper.QueryValue(partialDoc, keyValues.Skip(1)); if (doc == null) { return(null); } if (doc.IsBsonArray == false) { throw new Exception($"Data should be an array. ({doc.BsonType})"); } return(ConvertToTrackableList(doc.AsBsonArray)); }
// CreateAsync public Task CreateAsync(IMongoCollection <BsonDocument> collection, IDictionary <TKey, TValue> dictionary, params object[] keyValues) { if (keyValues.Length == 0) { throw new ArgumentException("At least 1 keyValue required."); } if (keyValues.Length == 1) { var bson = ConvertToBsonDocument(dictionary); bson.InsertAt(0, new BsonElement("_id", BsonValue.Create(keyValues[0]))); return(collection.InsertOneAsync(bson)); } else { var subKeys = keyValues.Skip(1).ToArray(); var update = BuildUpdatesForCreate(null, dictionary, subKeys); return(collection.UpdateOneAsync( Builders <BsonDocument> .Filter.And( Builders <BsonDocument> .Filter.Eq("_id", keyValues[0]), Builders <BsonDocument> .Filter.Exists(DocumentHelper.ToDotPath(subKeys), false)), update, new UpdateOptions { IsUpsert = true })); } }
public List <UpdateDefinition <BsonDocument> > BuildUpdatesForSave( UpdateDefinition <BsonDocument> update, TrackableSetTracker <T> tracker, params object[] keyValues) { var updates = new List <UpdateDefinition <BsonDocument> >(); var keyNamespace = DocumentHelper.ToDotPath(keyValues); if (tracker.AddValues.Any()) { updates.Add(update == null ? Builders <BsonDocument> .Update.AddToSetEach(keyNamespace, tracker.AddValues) : update.AddToSetEach(keyNamespace, tracker.AddValues)); update = null; } if (tracker.RemoveValues.Any()) { updates.Add(update == null ? Builders <BsonDocument> .Update.PullAll(keyNamespace, tracker.RemoveValues) : update.PullAll(keyNamespace, tracker.RemoveValues)); update = null; } if (update != null) { updates.Add(update); } return(updates); }
public async Task CreateAsync(IMongoCollection <BsonDocument> collection, T container, params object[] keyValues) { if (keyValues.Length == 0) { throw new ArgumentException("At least 1 keyValue required."); } var bson = ConvertToBsonDocument(container); if (keyValues.Length == 1) { bson.InsertAt(0, new BsonElement("_id", BsonValue.Create(keyValues[0]))); await collection.InsertOneAsync(bson); } else { var setPath = DocumentHelper.ToDotPath(keyValues.Skip(1)); await collection.UpdateOneAsync( Builders <BsonDocument> .Filter.And( Builders <BsonDocument> .Filter.Eq("_id", keyValues[0]), Builders <BsonDocument> .Filter.Exists(setPath, false)), Builders <BsonDocument> .Update.Set(setPath, bson), new UpdateOptions { IsUpsert = true }); } }
public UpdateDefinition <BsonDocument> BuildUpdatesForCreate( UpdateDefinition <BsonDocument> update, IList <T> list, params object[] keyValues) { var valuePath = DocumentHelper.ToDotPath(keyValues); var bson = ConvertToBsonArray(list); return(update == null ? Builders <BsonDocument> .Update.Set(valuePath, bson) : update.Set(valuePath, bson)); }
public UpdateDefinition <BsonDocument> BuildUpdatesForCreate( UpdateDefinition <BsonDocument> update, T poco, params object[] keyValues) { var keyPath = DocumentHelper.ToDotPath(keyValues); var bson = ConvertToBsonDocument(poco); return((update == null) ? Builders <BsonDocument> .Update.Set(keyPath, bson) : update.Set(keyPath, bson)); }
public UpdateDefinition <BsonDocument> BuildUpdatesForCreate(UpdateDefinition <BsonDocument> update, IDictionary <TKey, TValue> dictionary, params object[] keyValues) { var valuePath = DocumentHelper.ToDotPath(keyValues); var bson = ConvertToBsonDocument(dictionary); return(update == null ? Builders <BsonDocument> .Update.Set(valuePath, bson) : update.Set(valuePath, bson)); }
public async Task CreateAsync(IMongoCollection <BsonDocument> collection, T value, params object[] keyValues) { var bson = ConvertToBsonDocument(value); if (_idProperty != null) { if (keyValues.Length == 0) { // ConvertToBsonDocument uses BsonDocumentWrapper to serialize T // but it cannot handle returned _id property. // To workaround this limitation, force value to be serailized directly. bson = value.ToBsonDocument(_trackableType); await collection.InsertOneAsync(bson); var idValue = Convert.ChangeType(bson["_id"], _idProperty.PropertyType); _idProperty.SetValue(value, idValue); } else { var keyPath = keyValues.Length > 1 ? DocumentHelper.ToDotPath(keyValues.Skip(1)) + "." : ""; var setPath = keyPath + _idProperty.GetValue(value); await collection.UpdateOneAsync( Builders <BsonDocument> .Filter.And( Builders <BsonDocument> .Filter.Eq("_id", keyValues[0]), Builders <BsonDocument> .Filter.Exists(setPath, false)), Builders <BsonDocument> .Update.Set(setPath, bson), new UpdateOptions { IsUpsert = true }); } } else { if (keyValues.Length == 0) { await collection.InsertOneAsync(bson); } else if (keyValues.Length == 1) { bson["_id"] = BsonValue.Create(keyValues[0]); await collection.InsertOneAsync(bson); } else { var setPath = DocumentHelper.ToDotPath(keyValues.Skip(1)); await collection.UpdateOneAsync( Builders <BsonDocument> .Filter.And( Builders <BsonDocument> .Filter.Eq("_id", keyValues[0]), Builders <BsonDocument> .Filter.Exists(setPath, false)), Builders <BsonDocument> .Update.Set(setPath, bson), new UpdateOptions { IsUpsert = true }); } } }
public Task CreateAsync(IMongoCollection <BsonDocument> collection, IList <T> list, params object[] keyValues) { if (keyValues.Length < 2) { throw new ArgumentException("At least 2 keyValue required."); } var subKeys = keyValues.Skip(1).ToArray(); var update = BuildUpdatesForCreate(null, list, subKeys); return(collection.UpdateOneAsync( Builders <BsonDocument> .Filter.And( Builders <BsonDocument> .Filter.Eq("_id", keyValues[0]), Builders <BsonDocument> .Filter.Exists(DocumentHelper.ToDotPath(subKeys), false)), update, new UpdateOptions { IsUpsert = true })); }
public List <UpdateDefinition <BsonDocument> > BuildUpdatesForSave( UpdateDefinition <BsonDocument> update, TrackableListTracker <T> tracker, params object[] keyValues) { var keyNamespace = DocumentHelper.ToDotPath(keyValues); // Multiple push-back batching optimization if (tracker.ChangeList.Count > 1 && tracker.ChangeList.All(c => c.Operation == TrackableListOperation.PushBack)) { var newValues = tracker.ChangeList.Select(c => c.NewValue); return(new List <UpdateDefinition <BsonDocument> > { update == null ? Builders <BsonDocument> .Update.PushEach(keyNamespace, newValues) : update.PushEach(keyNamespace, newValues) }); } // Multiple push-front batching optimization if (tracker.ChangeList.Count > 1 && tracker.ChangeList.All(c => c.Operation == TrackableListOperation.PushFront)) { var newValues = tracker.ChangeList.Select(c => c.NewValue).Reverse(); return(new List <UpdateDefinition <BsonDocument> > { update == null ? Builders <BsonDocument> .Update.PushEach(keyNamespace, newValues, position : 0) : update.PushEach(keyNamespace, newValues, position: 0) }); } // List update can process only one change each time var updates = new List <UpdateDefinition <BsonDocument> >(); foreach (var change in tracker.ChangeList) { switch (change.Operation) { case TrackableListOperation.Insert: updates.Add(update == null ? Builders <BsonDocument> .Update.PushEach(keyNamespace, new[] { change.NewValue }, position: change.Index) : update.PushEach(keyNamespace, new[] { change.NewValue }, position: change.Index)); update = null; break; case TrackableListOperation.Remove: throw new Exception("Remove operation is not supported!"); case TrackableListOperation.Modify: updates.Add(update == null ? Builders <BsonDocument> .Update.Set(keyNamespace + "." + change.Index, change.NewValue) : update.Set(keyNamespace + "." + change.Index, change.NewValue)); break; case TrackableListOperation.PushFront: updates.Add(update == null ? Builders <BsonDocument> .Update.PushEach(keyNamespace, new[] { change.NewValue }, position: 0) : update.PushEach(keyNamespace, new[] { change.NewValue }, position: 0)); break; case TrackableListOperation.PushBack: updates.Add(update == null ? Builders <BsonDocument> .Update.Push(keyNamespace, change.NewValue) : update.Push(keyNamespace, change.NewValue)); break; case TrackableListOperation.PopFront: updates.Add(update == null ? Builders <BsonDocument> .Update.PopFirst(keyNamespace) : update.PopFirst(keyNamespace)); break; case TrackableListOperation.PopBack: updates.Add(update == null ? Builders <BsonDocument> .Update.PopLast(keyNamespace) : update.PopLast(keyNamespace)); break; } } if (update != null) { updates.Add(update); } return(updates); }