Example #1
0
        public void InsertOne_BsonDocument_ExpectedDocumentInserted()
        {
            /// Arrange
            // Get an id for the document.
            var id = Guid.NewGuid().ToString();

            // Get some expected bson document with the id.
            var expected = new BsonDocument()
                           .Add(new BsonElement("_id", BsonString.Create(id)))
                           .Add(new BsonElement("hello", BsonString.Create("world")));

            // Get a collection.
            var collection = new MongoClient("mongodb://localhost:27017")
                             .GetDatabase("jcs")
                             .GetCollection <BsonDocument>("events");

            /// Act
            // Insert the document into the collection.
            collection.InsertOne(expected);

            // Get the document back.
            var actual = collection.Find(
                new FilterDefinitionBuilder <BsonDocument>().Eq <string>(
                    new StringFieldDefinition <BsonDocument, string>("_id"), id))
                         .Single();

            /// Assert
            // Verify that the actual document matches the expected document.
            Assert.Equal(expected, actual);
        }
        public JsonResult Save(SceneCategorySaveModel model)
        {
            if (string.IsNullOrEmpty(model.Name.Trim()))
            {
                return(Json(new
                {
                    Code = 300,
                    Msg = "场景类别名称不允许为空!"
                }));
            }

            var mongo = new MongoHelper();

            if (string.IsNullOrEmpty(model.ID))
            {
                var doc = new BsonDocument();
                doc["Name"] = model.Name;
                mongo.InsertOne(Constant.SceneCategoryCollectionName, doc);
            }
            else
            {
                var filter = Builders <BsonDocument> .Filter.Eq("_id", ObjectId.Parse(model.ID));

                var update = Builders <BsonDocument> .Update.Set("Name", BsonString.Create(model.Name));

                mongo.UpdateOne(Constant.SceneCategoryCollectionName, filter, update);
            }

            return(Json(new
            {
                Code = 200,
                Msg = "保存成功!"
            }));
        }
Example #3
0
        public SearchResults GetReverseIncludes(IList <IKey> keys, IList <string> revIncludes)
        {
            BsonValue[] internal_ids = keys.Select(k => BsonString.Create(String.Format("{0}/{1}", k.TypeName, k.ResourceId))).ToArray();

            SearchResults results = new SearchResults();

            if (keys != null && revIncludes != null)
            {
                var riQueries = new List <FilterDefinition <BsonDocument> >();

                foreach (var revInclude in revIncludes)
                {
                    var ri = SM.ReverseInclude.Parse(revInclude);
                    if (!ri.SearchPath.Contains(".")) //for now, leave out support for chained revIncludes. There aren't that many anyway.
                    {
                        riQueries.Add(
                            Builders <BsonDocument> .Filter.And(
                                Builders <BsonDocument> .Filter.Eq(InternalField.RESOURCE, ri.ResourceType)
                                , Builders <BsonDocument> .Filter.In(ri.SearchPath, internal_ids)));
                    }
                }

                if (riQueries.Count > 0)
                {
                    var revIncludeQuery = Builders <BsonDocument> .Filter.Or(riQueries);

                    var resultKeys = CollectKeys(revIncludeQuery);
                    results = KeysToSearchResults(resultKeys);
                }
            }
            return(results);
        }
        public GenericDataContainer Reassemble(GenericDataContainer containerWithoutBinaryData, byte[] binaryData)
        {
            var containerWithData = CloneGenericDataContainer(containerWithoutBinaryData);

            containerWithData.Data.Set(binaryDataPath, BsonString.Create(Convert.ToBase64String(binaryData)));
            return(containerWithData);
        }
        public JsonResult Save(CategorySaveModel model)
        {
            if (string.IsNullOrEmpty(model.Name))
            {
                return(Json(new
                {
                    Code = 300,
                    Msg = "Name is not allowed to be empty."
                }));
            }

            if (model.Type == null)
            {
                return(Json(new
                {
                    Code = 300,
                    Msg = "Type is not allowed to be empty!"
                }));
            }

            var mongo = new MongoHelper();

            if (string.IsNullOrEmpty(model.ID))
            {
                var doc = new BsonDocument();
                doc["Name"] = model.Name;
                doc["Type"] = model.Type.Value.ToString();

                if (ConfigHelper.EnableAuthority)
                {
                    var user = UserHelper.GetCurrentUser();

                    if (user != null)
                    {
                        doc["UserID"] = user.ID;
                    }
                }

                mongo.InsertOne(Constant.CategoryCollectionName, doc);
            }
            else
            {
                var filter = Builders <BsonDocument> .Filter.Eq("_id", ObjectId.Parse(model.ID));

                var update1 = Builders <BsonDocument> .Update.Set("Name", BsonString.Create(model.Name));

                var update2 = Builders <BsonDocument> .Update.Set("Type", BsonString.Create(model.Type.Value.ToString()));

                var update = Builders <BsonDocument> .Update.Combine(update1, update2);

                mongo.UpdateOne(Constant.CategoryCollectionName, filter, update);
            }

            return(Json(new
            {
                Code = 200,
                Msg = "Saved successfully!"
            }));
        }
Example #6
0
        public IMongoQuery QueryDuplicatedName(Identity?groupId, string topicName, Identity?excludeId = null)
        {
            var query = excludeId.HasValue ?
                        Query.And(Query.EQ("Name", BsonString.Create(topicName)), Query.NE("_id", excludeId.Value.ToBson())) :
                        Query.EQ("Name", BsonString.Create(topicName));

            return(Query.And(query, Query.EQ("GroupId", groupId.ToBson())));
        }
Example #7
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static BsonValue String(object value)
        {
            string val = (string)value;

            if (value == null)
            {
                return(BsonNull.Value);
            }
            return(BsonString.Create(value));
        }
Example #8
0
 private BsonValue RenderOutput()
 {
     return
         (_outputDatabase == null?
          BsonString.Create(_outputCollection) :
              new BsonDocument
     {
         { "db", _outputDatabase }, { "coll", _outputCollection }
     });
 }
Example #9
0
        private BsonValue ParseSymbol()
        {
            VerifyToken(":");
            var nameToken = PopToken();

            if (nameToken.Type != JsonTokenType.String)
            {
                var message = string.Format("JSON reader expected a string but found: '{0}'", nameToken.Lexeme);
                throw new FileFormatException(message);
            }
            VerifyToken("}");
            return(BsonString.Create(nameToken.StringValue)); // will be converted to a BsonSymbol at a higher level
        }
Example #10
0
        public void unesiVijest(Result newArticle)
        {
            var collection = _database.GetCollection <BsonDocument>("articles");
            var id         = (int)collection.Count(new BsonDocument());

            var vijest = new BsonDocument {
                { "_id", BsonInt32.Create(id + 1) },
                { "headline", BsonString.Create(newArticle.headline) }, { "text", BsonString.Create(newArticle.text) },
                { "author", BsonString.Create(newArticle.author) }, { "comment", new BsonArray() },
                { "picture", new BsonBinaryData(newArticle.picture) }
            };

            collection.InsertOneAsync(vijest);
        }
Example #11
0
        public User CreateUser(int id = 1, int registartionId = 20, string name = "Ivan")
        {
            var currentTime    = DateTime.Now;
            var currentTimeUtc = DateTime.UtcNow;
            var userBson       = new BsonDocument()
            {
                {
                    "_id", id
                },
                {
                    "RegistartionId", registartionId //BsonInt32.Create(registartionId)
                },
                {
                    "Name", BsonString.Create(name)
                },
                {
                    "Birthday", new DateTime(1990, 10, 22)
                },
                //Driver will automatically convert your datetime to mongodb
                //format and store in as UTC date, and will convert back to your
                //local timezone back when you will read it
                //(actually you can change this behavior via driver settings).
                //So, take it in the mind that dates in mongodb always in UTC format.
                {
                    "RegistrationLocal", currentTime
                },
                {
                    "RegistrationUtc", currentTimeUtc
                }
            };

            _helper.WriteLine("Current time");
            _helper.WriteLine(currentTime.ToString("O"));
            _helper.WriteLine("Current time ToJson");
            _helper.WriteLine(currentTime.ToJson());
            _helper.WriteLine("Current UtcTime");
            _helper.WriteLine(currentTimeUtc.ToString("O"));
            _helper.WriteLine("Current UtcTime ToJson");
            _helper.WriteLine(currentTimeUtc.ToJson());
            _helper.WriteLine("User in bson");
            _helper.WriteLine(userBson.ToJson());
            _helper.WriteLine("User to poco");
            var userPoco = BsonSerializer.Deserialize <User>(userBson);

            _helper.WriteLine(userPoco.ToJson());
            userPoco.RegistrationLocal = currentTime;

            return(userPoco);
        }
Example #12
0
        public JsonResult Save(CategorySaveModel model)
        {
            if (string.IsNullOrEmpty(model.Name))
            {
                return(Json(new
                {
                    Code = 300,
                    Msg = "名称不允许为空!"
                }));
            }

            if (model.Type == null)
            {
                return(Json(new
                {
                    Code = 300,
                    Msg = "类型不允许为空!"
                }));
            }

            var mongo = new MongoHelper();

            if (string.IsNullOrEmpty(model.ID))
            {
                var doc = new BsonDocument();
                doc["Name"] = model.Name;
                doc["Type"] = model.Type.Value.ToString();
                mongo.InsertOne(Constant.CategoryCollectionName, doc);
            }
            else
            {
                var filter = Builders <BsonDocument> .Filter.Eq("_id", ObjectId.Parse(model.ID));

                var update1 = Builders <BsonDocument> .Update.Set("Name", BsonString.Create(model.Name));

                var update2 = Builders <BsonDocument> .Update.Set("Type", BsonString.Create(model.Type.Value.ToString()));

                var update = Builders <BsonDocument> .Update.Combine(update1, update2);

                mongo.UpdateOne(Constant.CategoryCollectionName, filter, update);
            }

            return(Json(new
            {
                Code = 200,
                Msg = "保存成功!"
            }));
        }
    public void GivenABsonDocumentWithANullForAnPossibleEmbeddedDocument_When_ThenAnInstanceIsSetAsTheEmbeddedDocument()
    {
        BsonSerializer.RegisterSerializationProvider(new VehicleEntryBsonSerializationProvider());
        var document = new BsonDocument()
        {
            { "OtherProperty1", BsonString.Create("12345") },
            { "OtherProperty2", BsonString.Create("67890") },
            { "VehicleEntry", BsonNull.Value },
        };
        var rootObject = BsonSerializer.Deserialize <RootObject>(document);

        Assert.That(rootObject.OtherProperty1, Is.EqualTo("12345"));
        Assert.That(rootObject.OtherProperty2, Is.EqualTo("67890"));
        Assert.That(rootObject.VehicleEntry, Is.Not.Null);
        Assert.That(rootObject.VehicleEntry.What, Is.EqualTo("Magic"));
    }
Example #14
0
        public void TestBsonDocumentWithBsonStringId()
        {
            _collection.RemoveAll();

            var doc = new BsonDocument {
                { "_id", BsonString.Create("") }, { "X", 1 }
            };

            _collection.Insert(doc);
            Assert.AreEqual("", doc["_id"].AsString);

            doc = new BsonDocument {
                { "_id", BsonString.Create("123") }, { "X", 1 }
            };
            _collection.Insert(doc);
        }
Example #15
0
 private BsonValue GetValue(object value)
 {
     if (value is DBNull || value == null)
     {
         return(BsonNull.Value);
     }
     else if (value is string)
     {
         return(BsonString.Create(value));
     }
     else if (value is bool)
     {
         return(BsonBoolean.Create(value));
     }
     else if (value is int || value is short || value is byte)
     {
         return(BsonInt32.Create(value));
     }
     else if (value is long)
     {
         return(BsonInt64.Create(value));
     }
     else if (value is decimal)
     {
         return(BsonDecimal128.Create(value));
     }
     else if (value is double || value is float)
     {
         return(BsonDouble.Create(value));
     }
     else if (value is DateTime)
     {
         return(BsonDateTime.Create(value));
     }
     else if (value is char c)
     {
         return(BsonString.Create("" + c));
     }
     else if (value is byte[])
     {
         return(BsonBinaryData.Create(value));
     }
     else
     {
         return(BsonString.Create(value.ToString()));
     }
 }
Example #16
0
        public async Task has_expected_bson_datatypes()
        {
            BadgeRepo badgeRepo = CreateBadgeRepo();
            // when
            PkmnSpecies randomSpecies = PkmnSpecies.OfId("9001");
            Badge       badge         = await badgeRepo.AddBadge(null, randomSpecies, Badge.BadgeSource.RunCaught);

            // then
            IMongoCollection <BsonDocument> badgesCollectionBson =
                badgeRepo.Collection.Database.GetCollection <BsonDocument>("badges");
            BsonDocument badgeBson = await badgesCollectionBson.Find(FilterDefinition <BsonDocument> .Empty).FirstAsync();

            Assert.AreEqual(BsonObjectId.Create(ObjectId.Parse(badge.Id)), badgeBson["_id"]);
            Assert.AreEqual(BsonNull.Value, badgeBson["user"]);
            Assert.AreEqual(BsonString.Create(randomSpecies.Id), badgeBson["species"]);
            Assert.AreEqual(BsonString.Create("run_caught"), badgeBson["source"]);
        }
        public void Add(QueryResult article)
        {
            var collection = database.GetCollection <BsonDocument>("articles");
            var Id         = (int)collection.Count(new BsonDocument());

            var news = new BsonDocument
            {
                { "_id", BsonInt32.Create(Id + 1) },
                { "headline", BsonString.Create(article.Headline) },
                { "body", BsonString.Create(article.Body) },
                { "author", BsonString.Create(article.Author) },
                { "comments", new BsonArray() },
                { "image", new BsonBinaryData(article.Image) }
            };

            collection.InsertOne(news);
        }
        public void Save_ResultIsProductAddedToPurchaseOrder_PersistsExpectedDocument()
        {
            /// Arrange
            // Get a product added to purchase order event.
            var @event = new ProductAddedToPurchaseOrder(
                purchaseOrderId: Guid.NewGuid(),
                productId: Guid.NewGuid(),
                measure: "EA",
                quantity: 14.25M);

            // Get some next id.
            var nextId = Guid.NewGuid();

            // Get the expected document dictionary.
            var expected = new BsonDocument()
                           .Add(new BsonElement("_id", BsonString.Create(nextId.ToString())))
                           .Add(new BsonElement("_type", BsonString.Create(nameof(ProductAddedToPurchaseOrder))))
                           .Add(new BsonElement(nameof(ProductAddedToPurchaseOrder.PurchaseOrderId), new BsonString(@event.PurchaseOrderId.ToString())))
                           .Add(new BsonElement(nameof(ProductAddedToPurchaseOrder.ProductId), new BsonString(@event.ProductId.ToString())))
                           .Add(new BsonElement(nameof(ProductAddedToPurchaseOrder.Measure), BsonString.Create(@event.Measure)))
                           .Add(new BsonElement(nameof(ProductAddedToPurchaseOrder.Quantity), BsonDecimal128.Create(@event.Quantity)));

            // Mock up a mongo client for the mongo db event store.
            BsonDocument actual     = null;
            var          collection = Mock.Create <IMongoCollection <BsonDocument> >();

            Mock.Arrange(() => collection.InsertOne(Arg.IsAny <BsonDocument>(), Arg.IsAny <InsertOneOptions>(), Arg.IsAny <CancellationToken>()))
            .DoInstead((BsonDocument document) => actual = document);
            var database = Mock.Create <IMongoDatabase>();

            Mock.Arrange(() => database.GetCollection <BsonDocument>(Arg.AnyString, Arg.IsAny <MongoCollectionSettings>()))
            .Returns(collection);
            var client = Mock.Create <IMongoClient>();

            Mock.Arrange(() => client.GetDatabase(Arg.AnyString, Arg.IsAny <MongoDatabaseSettings>()))
            .Returns(database);

            /// Act
            // Save the event.
            MongoDBEventStore.Save(client, nextId, @event);

            /// Assert
            // Verify that the actual document matches the expected document.
            Assert.Equal(expected, actual);
        }
Example #19
0
        public async Task log_has_expected_bson_datatypes()
        {
            MockClock clockMock = new MockClock();

            (IBank <TestUser> bank, IMongoCollection <TestUser> usersCollection) = CreateDbObjects(clockMock);
            TestUser user = new TestUser {
                Money = 10
            };
            await usersCollection.InsertOneAsync(user);

            List <int> list = new List <int> {
                1, 2, 3
            };
            Dictionary <string, bool> dictionary = new Dictionary <string, bool> {
                ["yes"] = true, ["no"] = false
            };
            await bank.PerformTransaction(new Transaction <TestUser>(user, 1, "test",
                                                                     new Dictionary <string, object?>
            {
                ["null_field"] = null,
                ["int_field"] = 42,
                ["string_field"] = "foo",
                ["list_field"] = list,
                ["dictionary_field"] = dictionary
            }));

            IMongoCollection <BsonDocument> transactionLogCollection =
                usersCollection.Database.GetCollection <BsonDocument>("transactionLog");
            BsonDocument log = await transactionLogCollection.Find(FilterDefinition <BsonDocument> .Empty).FirstAsync();

            Assert.IsInstanceOf <BsonObjectId>(log["_id"]);
            Assert.AreEqual(BsonString.Create(user.Id), log["user"]);
            Assert.AreEqual(BsonInt64.Create(1), log["change"]);
            Assert.AreEqual(BsonInt64.Create(10), log["old_balance"]);
            Assert.AreEqual(BsonInt64.Create(11), log["new_balance"]);
            Assert.AreEqual(clockMock.FixedCurrentInstant, log["timestamp"].ToUniversalTime().ToInstant());
            Assert.AreEqual(BsonString.Create("test"), log["type"]);
            Assert.AreEqual(BsonNull.Value, log["null_field"]);
            Assert.AreEqual(BsonInt32.Create(42), log["int_field"]);
            Assert.AreEqual(BsonString.Create("foo"), log["string_field"]);
            Assert.AreEqual(BsonArray.Create(list), log["list_field"]);
            Assert.AreEqual(BsonDocument.Create(dictionary), log["dictionary_field"]);
        }
Example #20
0
        // public methods
        /// <summary>
        /// Deserializes an object from a BsonReader.
        /// </summary>
        /// <param name="bsonReader">The BsonReader.</param>
        /// <param name="nominalType">The nominal type of the object.</param>
        /// <param name="actualType">The actual type of the object.</param>
        /// <param name="options">The serialization options.</param>
        /// <returns>An object.</returns>
        public override object Deserialize(
            BsonReader bsonReader,
            Type nominalType,
            Type actualType,
            IBsonSerializationOptions options)
        {
            VerifyTypes(nominalType, actualType, typeof(BsonString));

            var bsonType = bsonReader.GetCurrentBsonType();

            if (bsonType == BsonType.Null)
            {
                bsonReader.ReadNull();
                return(null);
            }
            else
            {
                return(BsonString.Create((string)StringSerializer.Instance.Deserialize(bsonReader, typeof(string), options)));
            }
        }
Example #21
0
        public async Task <OperationResult> ExecuteAsync(CancellationToken cancellationToken)
        {
            try
            {
                string result;

                if (_session == null)
                {
                    result = await _collection.Indexes.CreateOneAsync(_createIndexModel, cancellationToken : cancellationToken);
                }
                else
                {
                    result = await _collection.Indexes.CreateOneAsync(_session, _createIndexModel, cancellationToken : cancellationToken);
                }

                return(OperationResult.FromResult(BsonString.Create(result)));
            }
            catch (Exception exception)
            {
                return(OperationResult.FromException(exception));
            }
        }
        public void Save_ResultIsVendorDoesNotExist_PersistsExpectedDocument()
        {
            /// Arrange
            // Get a purchase order created event.
            var @event = new VendorDoesNotExist(
                vendorId: Guid.NewGuid());

            // Get some next id.
            var nextId = Guid.NewGuid();

            // Get the expected document dictionary.
            var expected = new BsonDocument()
                           .Add(new BsonElement("_id", BsonString.Create(nextId.ToString())))
                           .Add(new BsonElement("_type", BsonString.Create(nameof(VendorDoesNotExist))))
                           .Add(new BsonElement(nameof(VendorDoesNotExist.VendorId), new BsonString(@event.VendorId.ToString())));

            // Mock up a mongo client for the mongo db event store.
            BsonDocument actual     = null;
            var          collection = Mock.Create <IMongoCollection <BsonDocument> >();

            Mock.Arrange(() => collection.InsertOne(Arg.IsAny <BsonDocument>(), Arg.IsAny <InsertOneOptions>(), Arg.IsAny <CancellationToken>()))
            .DoInstead((BsonDocument document) => actual = document);
            var database = Mock.Create <IMongoDatabase>();

            Mock.Arrange(() => database.GetCollection <BsonDocument>(Arg.AnyString, Arg.IsAny <MongoCollectionSettings>()))
            .Returns(collection);
            var client = Mock.Create <IMongoClient>();

            Mock.Arrange(() => client.GetDatabase(Arg.AnyString, Arg.IsAny <MongoDatabaseSettings>()))
            .Returns(database);

            /// Act
            // Save the event.
            MongoDBEventStore.Save(client, nextId, @event);

            /// Assert
            // Verify that the actual document matches the expected document.
            Assert.Equal(expected, actual);
        }
        public void TestBsonString()
        {
            var booleanString  = BsonString.Create("true");
            var dateTimeString = BsonString.Create("2011-01-20");
            var doubleString   = BsonString.Create("1.5");
            var intString      = BsonString.Create("1");

            Assert.AreEqual(true, Convert.ToBoolean(booleanString));
            Assert.AreEqual(1, Convert.ToByte(intString));
            Assert.AreEqual('1', Convert.ToChar(intString));
            Assert.AreEqual(new DateTime(2011, 1, 20), Convert.ToDateTime(dateTimeString));
            Assert.AreEqual(1.5m, Convert.ToDecimal(doubleString, CultureInfo.InvariantCulture));
            Assert.AreEqual(1.5, Convert.ToDouble(doubleString, CultureInfo.InvariantCulture));
            Assert.AreEqual(1, Convert.ToInt16(intString));
            Assert.AreEqual(1, Convert.ToInt32(intString));
            Assert.AreEqual(1, Convert.ToInt64(intString));
            Assert.AreEqual(1, Convert.ToSByte(intString));
            Assert.AreEqual(1.5F, Convert.ToSingle(doubleString, CultureInfo.InvariantCulture));
            Assert.AreEqual("1.5", Convert.ToString(doubleString, CultureInfo.InvariantCulture));
            Assert.AreEqual(1, Convert.ToUInt16(intString));
            Assert.AreEqual(1, Convert.ToUInt32(intString));
            Assert.AreEqual(1, Convert.ToUInt64(intString));
        }
Example #24
0
 public IMongoQuery QueryDuplicatedName(string groupName, Identity?excludeId = null)
 {
     return(excludeId.HasValue ?
            Query.And(Query.EQ("Name", BsonString.Create(groupName)), Query.NE("_id", excludeId.Value.ToBson())) :
            Query.EQ("Name", BsonString.Create(groupName)));
 }
Example #25
0
        // This process updates acquired values in the mongodb collection for realtime data
        static public async void ProcessMongo(JSONSCADAConfig jsConfig)
        {
            do
            {
                try
                {
                    var Client     = ConnectMongoClient(jsConfig);
                    var DB         = Client.GetDatabase(jsConfig.mongoDatabaseName);
                    var collection =
                        DB.GetCollection <rtData>(RealtimeDataCollectionName);
                    var collection_cmd =
                        DB
                        .GetCollection
                        <rtCommand>(CommandsQueueCollectionName);

                    Log("MongoDB Update Thread Started...");

                    var listWrites = new List <WriteModel <rtData> >();
                    do
                    {
                        //if (LogLevel >= LogLevelBasic && OPCDataQueue.Count > 0)
                        //  Log("MongoDB - Data queue size: " +  OPCDataQueue.Count, LogLevelBasic);

                        // Log("1");

                        bool isMongoLive =
                            DB
                            .RunCommandAsync((Command <BsonDocument>)
                                             "{ping:1}")
                            .Wait(1000);
                        if (!isMongoLive)
                        {
                            throw new Exception("Error on MongoDB connection ");
                        }

                        // Log("2");
                        IEC_CmdAck ia;
                        if (OPCCmdAckQueue.Count > 0)
                        {
                            while (OPCCmdAckQueue.TryDequeue(out ia))
                            {
                                var filter1 =
                                    Builders <rtCommand>
                                    .Filter
                                    .Eq(m => m.protocolSourceConnectionNumber,
                                        ia.conn_number);

                                var filter2 =
                                    Builders <rtCommand>
                                    .Filter
                                    .Eq(m => m.protocolSourceObjectAddress,
                                        ia.object_address);

                                var filter =
                                    Builders <rtCommand>
                                    .Filter
                                    .And(filter1, filter2);

                                var update =
                                    Builders <rtCommand>
                                    .Update
                                    .Set(m => m.ack, ia.ack)
                                    .Set(m => m.ackTimeTag, ia.ack_time_tag);

                                // sort by priority then by insert order
                                var sort =
                                    Builders <rtCommand> .Sort.Descending("$natural");

                                var options =
                                    new FindOneAndUpdateOptions <rtCommand, rtCommand
                                                                 >();
                                options.IsUpsert = false;
                                options.Sort     = sort;
                                await collection_cmd
                                .FindOneAndUpdateAsync(filter, update, options);
                            }
                        }
                        // Log("3");

                        Stopwatch stopWatch = new Stopwatch();
                        stopWatch.Start();

                        OPC_Value iv;
                        while (!OPCDataQueue.IsEmpty && OPCDataQueue.TryPeek(out iv) && OPCDataQueue.TryDequeue(out iv))
                        {
                            // Log("3.1");
                            DateTime  tt     = DateTime.MinValue;
                            BsonValue bsontt = BsonNull.Value;
                            try
                            {
                                if (iv.hasSourceTimestamp)
                                {
                                    bsontt = BsonValue.Create(iv.sourceTimestamp);
                                }
                            }
                            catch
                            {
                                tt     = DateTime.MinValue;
                                bsontt = BsonNull.Value;
                            }

                            BsonDocument valJSON = new BsonDocument();
                            try
                            {
                                valJSON = BsonDocument.Parse(iv.valueJson);
                            }
                            catch (Exception e)
                            {
                                Log(iv.conn_name + " - " + e.Message);
                            }

                            // Log("3.2");

                            if (iv.selfPublish)
                            {
                                string tag = TagFromOPCParameters(iv);
                                if (!InsertedTags.Contains(tag))
                                {
                                    // look for the tag
                                    var task = await collection.FindAsync <rtData>(new BsonDocument {
                                        {
                                            "tag", TagFromOPCParameters(iv)
                                        }
                                    });

                                    List <rtData> list = await task.ToListAsync();

                                    // await Task.Delay(10);
                                    //Thread.Yield();
                                    //Thread.Sleep(1);

                                    InsertedTags.Add(tag);
                                    if (list.Count == 0)
                                    {
                                        Log(iv.conn_name + " - INSERT - " + iv.address);
                                        // hash to create keys
                                        var id         = HashStringToInt(iv.address);
                                        var insert     = newRealtimeDoc(iv, id);
                                        int conn_index = 0;
                                        // normal for loop
                                        for (int index = 0; index < OPCUAconns.Count; index++)
                                        {
                                            if (OPCUAconns[index].protocolConnectionNumber == iv.conn_number)
                                            {
                                                conn_index = index;
                                            }
                                        }
                                        insert.protocolSourcePublishingInterval = OPCUAconns[conn_index].autoCreateTagPublishingInterval;
                                        insert.protocolSourceSamplingInterval   = OPCUAconns[conn_index].autoCreateTagSamplingInterval;
                                        insert.protocolSourceQueueSize          = OPCUAconns[conn_index].autoCreateTagQueueSize;
                                        listWrites
                                        .Add(new InsertOneModel <rtData>(insert));
                                    }
                                }
                            }

                            //below code will update one record of the data
                            var update =
                                new BsonDocument {
                                {
                                    "$set",
                                    new BsonDocument {
                                        {
                                            "sourceDataUpdate",
                                            new BsonDocument {
                                                {
                                                    "valueBsonAtSource", valJSON
                                                },
                                                {
                                                    "valueAtSource",
                                                    BsonDouble
                                                    .Create(iv.value)
                                                },
                                                {
                                                    "valueStringAtSource",
                                                    BsonString
                                                    .Create(iv.valueString)
                                                },
                                                {
                                                    "asduAtSource",
                                                    BsonString
                                                    .Create(iv.asdu.ToString())
                                                },
                                                {
                                                    "causeOfTransmissionAtSource",
                                                    BsonString.Create(iv.cot.ToString())
                                                },
                                                {
                                                    "timeTagAtSource",
                                                    bsontt
                                                },
                                                {
                                                    "timeTagAtSourceOk",
                                                    BsonBoolean
                                                    .Create(iv.hasSourceTimestamp)
                                                },
                                                {
                                                    "timeTag",
                                                    BsonValue
                                                    .Create(iv
                                                            .serverTimestamp)
                                                },
                                                {
                                                    "notTopicalAtSource",
                                                    BsonBoolean
                                                    .Create(false)
                                                },
                                                {
                                                    "invalidAtSource",
                                                    BsonBoolean
                                                    .Create(!iv
                                                            .quality
                                                            )
                                                },
                                                {
                                                    "overflowAtSource",
                                                    BsonBoolean
                                                    .Create(false)
                                                },
                                                {
                                                    "blockedAtSource",
                                                    BsonBoolean
                                                    .Create(false)
                                                },
                                                {
                                                    "substitutedAtSource",
                                                    BsonBoolean
                                                    .Create(false)
                                                }
                                            }
                                        }
                                    }
                                }
                            };

                            var filt =
                                new rtFilt
                            {
                                protocolSourceConnectionNumber =
                                    iv.conn_number,
                                protocolSourceCommonAddress =
                                    iv.common_address,
                                protocolSourceObjectAddress = iv.address
                            };
                            Log("MongoDB - ADD " + iv.address + " " + iv.value,
                                LogLevelDebug);
                            // Log("3.3");

                            listWrites
                            .Add(new UpdateOneModel <rtData>(filt
                                                             .ToBsonDocument(),
                                                             update));

                            if (listWrites.Count >= BulkWriteLimit)
                            {
                                break;
                            }

                            if (stopWatch.ElapsedMilliseconds > 400)
                            {
                                break;
                            }

                            // Log("3.4 - Write buffer " + listWrites.Count + " Data " + OPCDataQueue.Count);

                            // give time to breath each 250 dequeues
                            //if ((listWrites.Count % 250)==0)
                            //{
                            //   await Task.Delay(10);
                            //Thread.Yield();
                            //Thread.Sleep(1);
                            //}
                        }

                        // Log("4");
                        if (listWrites.Count > 0)
                        {
                            Log("MongoDB - Bulk write " + listWrites.Count + " Data " + OPCDataQueue.Count);
                            var bulkWriteResult =
                                await collection.BulkWriteAsync(listWrites);

                            listWrites.Clear();

                            //Thread.Yield();
                            //Thread.Sleep(1);
                        }

                        if (OPCDataQueue.IsEmpty)
                        {
                            await Task.Delay(250);
                        }
                        // Log("6");
                    }while (true);
                }
                catch (Exception e)
                {
                    Log("Exception Mongo");
                    Log(e);
                    Log(e
                        .ToString()
                        .Substring(0,
                                   e.ToString().IndexOf(Environment.NewLine)));
                    Thread.Sleep(1000);

                    while (OPCDataQueue.Count > DataBufferLimit // do not let data queue grow more than a limit
                           )
                    {
                        Log("MongoDB - Dequeue Data", LogLevelDetailed);
                        OPC_Value iv;
                        OPCDataQueue.TryDequeue(out iv);
                    }
                }
            }while (true);
        }
Example #26
0
        public static BsonValue Create(this BsonType bsonType, object o)
        {
            BsonValue value = BsonNull.Value;

            try
            {
                switch (bsonType)
                {
                case BsonType.EndOfDocument:
                    break;

                case BsonType.Double:
                    value = BsonDouble.Create(o);
                    break;

                case BsonType.String:
                    value = BsonString.Create(o);
                    break;

                case BsonType.Document:
                    value = BsonDocument.Create(o);
                    break;

                case BsonType.Array:
                    value = BsonArray.Create(o);
                    break;

                case BsonType.Binary:
                    value = BsonBinaryData.Create(o);
                    break;

                case BsonType.Undefined:
                    break;

                case BsonType.ObjectId:
                    value = BsonObjectId.Create(o);
                    break;

                case BsonType.Boolean:
                    value = BsonBoolean.Create(o);
                    break;

                case BsonType.DateTime:
                    value = BsonDateTime.Create(o);
                    break;

                case BsonType.Null:
                    value = BsonNull.Value;
                    break;

                case BsonType.RegularExpression:
                    value = BsonRegularExpression.Create(o);
                    break;

                case BsonType.JavaScript:
                    value = BsonJavaScript.Create(o);
                    break;

                case BsonType.Symbol:
                    value = BsonSymbol.Create(o);
                    break;

                case BsonType.JavaScriptWithScope:
                    value = BsonJavaScriptWithScope.Create(o);
                    break;

                case BsonType.Int32:
                    value = BsonInt32.Create(o);
                    break;

                case BsonType.Timestamp:
                    value = BsonTimestamp.Create(o);
                    break;

                case BsonType.Int64:
                    value = BsonInt64.Create(o);
                    break;

                case BsonType.MaxKey:
                    value = BsonValue.Create(o);
                    break;

                case BsonType.MinKey:
                    value = BsonValue.Create(o);
                    break;
                }
            }
            catch
            {
            }

            return(value);
        }
Example #27
0
        // This process monitor and updates redundancy control of the driver instance in mongodb
        static async void ProcessRedundancyMongo(JSONSCADAConfig jsConfig)
        {
            do
            {
                try
                {
                    var lastActiveNodeKeepAliveTimeTag = DateTime.MinValue;
                    var countKeepAliveUpdates          = 0;
                    var countKeepAliveUpdatesLimit     = 4;
                    var Client = ConnectMongoClient(jsConfig);
                    var DB     = Client.GetDatabase(jsConfig.mongoDatabaseName);

                    // read and process instances configuration
                    var collconns =
                        DB
                        .GetCollection
                        <IEC10X_connection
                        >(ProtocolConnectionsCollectionName);
                    var collinsts =
                        DB
                        .GetCollection
                        <protocolDriverInstancesClass
                        >(ProtocolDriverInstancesCollectionName);
                    do
                    {
                        bool isMongoLive =
                            DB
                            .RunCommandAsync((Command <BsonDocument>)
                                             "{ping:1}")
                            .Wait(1000);
                        if (!isMongoLive)
                        {
                            throw new Exception("Error on MongoDB connection ");
                        }

                        var instances =
                            collinsts
                            .Find(inst =>
                                  inst.protocolDriver == ProtocolDriverName &&
                                  inst.protocolDriverInstanceNumber == ProtocolDriverInstanceNumber)
                            .ToList();
                        var foundinstance = false;
                        foreach (protocolDriverInstancesClass inst in instances)
                        {
                            foundinstance = true;

                            var nodefound = false;
                            foreach (var name in inst.nodeNames)
                            {
                                if (JSConfig.nodeName == name)
                                {
                                    nodefound = true;
                                }
                            }
                            if (!nodefound)
                            {
                                Log("Node '" +
                                    JSConfig.nodeName +
                                    "' not found in instances configuration!");
                                Environment.Exit(-1);
                            }

                            if (inst.activeNodeName == JSConfig.nodeName)
                            {
                                if (!Active) // will go active
                                {
                                    Log("Redundancy - ACTIVATING this Node!");
                                }
                                Active = true;
                                countKeepAliveUpdates = 0;
                            }
                            else
                            {
                                if (Active) // will go inactive
                                {           // wait a random time
                                    Log("Redundancy - DEACTIVATING this Node (other node active)!");
                                    countKeepAliveUpdates = 0;
                                    Random rnd = new Random();
                                    Thread.Sleep(rnd.Next(1000, 5000));
                                }
                                Active = false;
                                if (lastActiveNodeKeepAliveTimeTag == inst.activeNodeKeepAliveTimeTag)
                                {
                                    countKeepAliveUpdates++;
                                }
                                lastActiveNodeKeepAliveTimeTag = inst.activeNodeKeepAliveTimeTag;
                                if (countKeepAliveUpdates > countKeepAliveUpdatesLimit)
                                { // time exceeded, be active
                                    Log("Redundancy - ACTIVATING this Node!");
                                    Active = true;
                                }
                            }

                            if (Active)
                            {
                                Log("Redundancy - This node is active.");

                                // update keep alive time
                                var filter1 =
                                    Builders <protocolDriverInstancesClass>
                                    .Filter
                                    .Eq(m => m.protocolDriver,
                                        ProtocolDriverName);

                                var filter2 =
                                    Builders <protocolDriverInstancesClass>
                                    .Filter
                                    .Eq(m => m.protocolDriverInstanceNumber,
                                        ProtocolDriverInstanceNumber);

                                var filter =
                                    Builders <protocolDriverInstancesClass>
                                    .Filter
                                    .And(filter1, filter2);

                                var update =
                                    Builders <protocolDriverInstancesClass>
                                    .Update
                                    .Set(m => m.activeNodeName, JSConfig.nodeName)
                                    .Set(m => m.activeNodeKeepAliveTimeTag, DateTime.Now);

                                var options =
                                    new FindOneAndUpdateOptions <protocolDriverInstancesClass, protocolDriverInstancesClass
                                                                 >();
                                options.IsUpsert = false;
                                await collinsts
                                .FindOneAndUpdateAsync(filter, update, options);

                                // update statistics for connections
                                foreach (IEC10X_connection srv in IEC10Xconns)
                                {
                                    if (!(srv.master is null))
                                    {
                                        var stats = srv.master;
                                        var filt  =
                                            new BsonDocument(new BsonDocument("protocolConnectionNumber",
                                                                              srv.protocolConnectionNumber));
                                        var upd =
                                            new BsonDocument("$set", new BsonDocument {
                                            { "stats", new BsonDocument {
                                                  { "nodeName", JSConfig.nodeName },
                                                  { "timeTag", BsonDateTime.Create(DateTime.Now) },
                                                  { "linkLayerState", BsonString.Create(srv.master.GetLinkLayerState(srv.remoteLinkAddress).ToString()) },
                                              } },
                                        });
                                        var res = collconns.UpdateOneAsync(filt, upd);
                                    }
                                }
                            }
                            else
                            {
                                if (inst.activeNodeName != "")
                                {
                                    Log("Redundancy - This node is INACTIVE! Node '" + inst.activeNodeName + "' is active, wait...");
                                }
                                else
                                {
                                    Log("Redundancy - This node is INACTIVE! No node is active, wait...");
                                }
                            }

                            break; // process just first result
                        }

                        if (!foundinstance)
                        {
                            if (Active) // will go inactive
                            {           // wait a random time
                                Log("Redundancy - DEACTIVATING this Node (no instance found)!");
                                countKeepAliveUpdates = 0;
                                Random rnd = new Random();
                                Thread.Sleep(rnd.Next(1000, 5000));
                            }
                            Active = false;
                        }

                        Thread.Sleep(5000);
                    }while (true);
                }
                catch (Exception e)
                {
                    Log("Exception Mongo");
                    Log(e);
                    Log(e
                        .ToString()
                        .Substring(0,
                                   e.ToString().IndexOf(Environment.NewLine)));
                    System.Threading.Thread.Sleep(3000);
                }
            }while (true);
        }
Example #28
0
        static public int AutoKeyMultiplier = 1000000; // maximum number of points on each connection self-published (auto numbered points)

        // This process updates acquired values in the mongodb collection for realtime data
        static public async void ProcessMongo(JSONSCADAConfig jsConfig)
        {
            do
            {
                try
                {
                    var Client     = ConnectMongoClient(jsConfig);
                    var DB         = Client.GetDatabase(jsConfig.mongoDatabaseName);
                    var collection =
                        DB.GetCollection <rtData>(RealtimeDataCollectionName);
                    var collectionId =
                        DB.GetCollection <rtDataId>(RealtimeDataCollectionName);
                    var collection_cmd =
                        DB
                        .GetCollection
                        <rtCommand>(CommandsQueueCollectionName);

                    Log("MongoDB Update Thread Started...");

                    var listWrites = new List <WriteModel <rtData> >();
                    do
                    {
                        //if (LogLevel >= LogLevelBasic && OPCDataQueue.Count > 0)
                        //  Log("MongoDB - Data queue size: " +  OPCDataQueue.Count, LogLevelBasic);

                        bool isMongoLive =
                            DB
                            .RunCommandAsync((Command <BsonDocument>)
                                             "{ping:1}")
                            .Wait(2500);
                        if (!isMongoLive)
                        {
                            throw new Exception("Error on MongoDB connection ");
                        }

                        Stopwatch stopWatch = new Stopwatch();
                        stopWatch.Start();

                        OPC_Value iv;
                        while (!OPCDataQueue.IsEmpty && OPCDataQueue.TryPeek(out iv) && OPCDataQueue.TryDequeue(out iv))
                        {
                            DateTime  tt     = DateTime.MinValue;
                            BsonValue bsontt = BsonNull.Value;
                            try
                            {
                                if (iv.hasSourceTimestamp)
                                {
                                    bsontt = BsonValue.Create(iv.sourceTimestamp);
                                }
                            }
                            catch
                            {
                                tt     = DateTime.MinValue;
                                bsontt = BsonNull.Value;
                            }

                            BsonDocument valJSON = new BsonDocument();
                            try
                            {
                                valJSON = BsonDocument.Parse(iv.valueJson);
                            }
                            catch (Exception e)
                            {
                                Log(iv.conn_name + " - " + e.Message);
                            }

                            if (iv.selfPublish)
                            {
                                // find the json-scada connection for this received value
                                int conn_index = 0;
                                for (int index = 0; index < OPCUAconns.Count; index++)
                                {
                                    if (OPCUAconns[index].protocolConnectionNumber == iv.conn_number)
                                    {
                                        conn_index = index;
                                    }
                                }

                                string tag = TagFromOPCParameters(iv);
                                if (!OPCUAconns[conn_index].InsertedTags.Contains(tag))
                                { // tag not yet inserted
                                  // put the tag in the list of inserted, then insert it

                                    OPCUAconns[conn_index].InsertedTags.Add(tag);

                                    Log(iv.conn_name + " - INSERT NEW TAG: " + tag + " - Addr:" + iv.address);

                                    // find a new freee _id key based on the connection number
                                    if (OPCUAconns[conn_index].LastNewKeyCreated == 0)
                                    {
                                        Double AutoKeyId = iv.conn_number * AutoKeyMultiplier;
                                        var    results   = collectionId.Find <rtDataId>(new BsonDocument {
                                            { "_id", new BsonDocument {
                                                  { "$gt", AutoKeyId },
                                                  { "$lt", (iv.conn_number + 1) * AutoKeyMultiplier }
                                              } }
                                        }).Sort(Builders <rtDataId> .Sort.Descending("_id"))
                                                           .Limit(1)
                                                           .ToList();

                                        if (results.Count > 0)
                                        {
                                            OPCUAconns[conn_index].LastNewKeyCreated = results[0]._id.ToDouble() + 1;
                                        }
                                        else
                                        {
                                            OPCUAconns[conn_index].LastNewKeyCreated = AutoKeyId;
                                        }
                                    }
                                    else
                                    {
                                        OPCUAconns[conn_index].LastNewKeyCreated = OPCUAconns[conn_index].LastNewKeyCreated + 1;
                                    }

                                    var id = OPCUAconns[conn_index].LastNewKeyCreated;

                                    // will enqueue to insert the new tag into mongo DB
                                    var insert = newRealtimeDoc(iv, id);
                                    insert.protocolSourcePublishingInterval = OPCUAconns[conn_index].autoCreateTagPublishingInterval;
                                    insert.protocolSourceSamplingInterval   = OPCUAconns[conn_index].autoCreateTagSamplingInterval;
                                    insert.protocolSourceQueueSize          = OPCUAconns[conn_index].autoCreateTagQueueSize;
                                    listWrites
                                    .Add(new InsertOneModel <rtData>(insert));

                                    // will imediatelly be followed by an update below (to the same tag)
                                }
                            }

                            // update one existing document with received tag value (realtimeData)
                            var update =
                                new BsonDocument {
                                {
                                    "$set",
                                    new BsonDocument {
                                        {
                                            "sourceDataUpdate",
                                            new BsonDocument {
                                                {
                                                    "valueBsonAtSource", valJSON
                                                },
                                                {
                                                    "valueAtSource",
                                                    BsonDouble
                                                    .Create(iv.value)
                                                },
                                                {
                                                    "valueStringAtSource",
                                                    BsonString
                                                    .Create(iv.valueString)
                                                },
                                                {
                                                    "asduAtSource",
                                                    BsonString
                                                    .Create(iv.asdu.ToString())
                                                },
                                                {
                                                    "causeOfTransmissionAtSource",
                                                    BsonString.Create(iv.cot.ToString())
                                                },
                                                {
                                                    "timeTagAtSource",
                                                    bsontt
                                                },
                                                {
                                                    "timeTagAtSourceOk",
                                                    BsonBoolean
                                                    .Create(iv.hasSourceTimestamp)
                                                },
                                                {
                                                    "timeTag",
                                                    BsonValue
                                                    .Create(iv
                                                            .serverTimestamp)
                                                },
                                                {
                                                    "notTopicalAtSource",
                                                    BsonBoolean
                                                    .Create(false)
                                                },
                                                {
                                                    "invalidAtSource",
                                                    BsonBoolean
                                                    .Create(!iv
                                                            .quality
                                                            )
                                                },
                                                {
                                                    "overflowAtSource",
                                                    BsonBoolean
                                                    .Create(false)
                                                },
                                                {
                                                    "blockedAtSource",
                                                    BsonBoolean
                                                    .Create(false)
                                                },
                                                {
                                                    "substitutedAtSource",
                                                    BsonBoolean
                                                    .Create(false)
                                                }
                                            }
                                        }
                                    }
                                }
                            };

                            // update filter, avoids updating commands that can have the same address as supervised points
                            var filt =
                                new rtFilt
                            {
                                protocolSourceConnectionNumber =
                                    iv.conn_number,
                                protocolSourceObjectAddress = iv.address,
                                origin = "supervised"
                            };
                            Log("MongoDB - ADD " + iv.address + " " + iv.value,
                                LogLevelDebug);

                            listWrites
                            .Add(new UpdateOneModel <rtData>(filt
                                                             .ToBsonDocument(),
                                                             update));

                            if (listWrites.Count >= BulkWriteLimit)
                            {
                                break;
                            }

                            if (stopWatch.ElapsedMilliseconds > 400)
                            {
                                break;
                            }

                            // Log("Write buffer " + listWrites.Count + " Data " + OPCDataQueue.Count);

                            // give time to breath each 250 dequeues
                            //if ((listWrites.Count % 250)==0)
                            //{
                            //   await Task.Delay(10);
                            //Thread.Yield();
                            //Thread.Sleep(1);
                            //}
                        }

                        if (listWrites.Count > 0)
                        {
                            Log("MongoDB - Bulk writing " + listWrites.Count + ", Total enqueued data " + OPCDataQueue.Count);
                            var bulkWriteResult =
                                await collection.BulkWriteAsync(listWrites);

                            listWrites.Clear();

                            Log($"MongoDB - OK:{bulkWriteResult.IsAcknowledged} - Inserted:{bulkWriteResult.InsertedCount} - Updated:{bulkWriteResult.ModifiedCount}");

                            //Thread.Yield();
                            //Thread.Sleep(1);
                        }

                        if (OPCDataQueue.IsEmpty)
                        {
                            await Task.Delay(250);
                        }
                    }while (true);
                }
                catch (Exception e)
                {
                    Log("Exception Mongo");
                    Log(e);
                    Log(e
                        .ToString()
                        .Substring(0,
                                   e.ToString().IndexOf(Environment.NewLine)));
                    Thread.Sleep(1000);

                    while (OPCDataQueue.Count > DataBufferLimit // do not let data queue grow more than a limit
                           )
                    {
                        Log("MongoDB - Dequeue Data", LogLevelDetailed);
                        OPC_Value iv;
                        OPCDataQueue.TryDequeue(out iv);
                    }
                }
            }while (true);
        }
        public void Save_ResultIsPurchaseOrderCreated_PersistsExpectedDocument(PurchaseOrderStatus status)
        {
            /// Arrange
            // Get a purchase order created event.
            var @event = new PurchaseOrderCreated(
                purchaseOrderId: Guid.NewGuid(),
                status: status,
                vendorId: Guid.NewGuid(),
                lines: Enumerable.Empty <PurchaseOrderLine>()
                .Append(new PurchaseOrderLine(
                            productId: Guid.NewGuid(),
                            quantity: 14.25M,
                            measure: "EA",
                            pricePerUnit: 2.24M))
                .Append(new PurchaseOrderLine(
                            productId: Guid.NewGuid(),
                            quantity: 5.5M,
                            measure: "FT",
                            pricePerUnit: 0.75M)));

            // Get some next id.
            var nextId = Guid.NewGuid();

            // Get the expected document dictionary.
            var expected = new BsonDocument()
                           .Add(new BsonElement("_id", BsonString.Create(nextId.ToString())))
                           .Add(new BsonElement("_type", BsonString.Create(nameof(PurchaseOrderCreated))))
                           .Add(new BsonElement(nameof(PurchaseOrderCreated.PurchaseOrderId), new BsonString(@event.PurchaseOrderId.ToString())))
                           .Add(new BsonElement(nameof(PurchaseOrderCreated.Status), new BsonString(Enum.GetName <PurchaseOrderStatus>(@event.Status))))
                           .Add(new BsonElement(nameof(PurchaseOrderCreated.VendorId), new BsonString(@event.VendorId.ToString())))
                           .Add(new BsonElement(nameof(PurchaseOrderCreated.Lines), new BsonArray()
                                                .Add(new BsonDocument()
                                                     .Add(new BsonElement(nameof(PurchaseOrderLine.ProductId), BsonString.Create(@event.Lines.ElementAt(0).ProductId.ToString())))
                                                     .Add(new BsonElement(nameof(PurchaseOrderLine.Quantity), BsonDecimal128.Create(@event.Lines.ElementAt(0).Quantity)))
                                                     .Add(new BsonElement(nameof(PurchaseOrderLine.Measure), BsonString.Create(@event.Lines.ElementAt(0).Measure)))
                                                     .Add(new BsonElement(nameof(PurchaseOrderLine.PricePerUnit), BsonDecimal128.Create(@event.Lines.ElementAt(0).PricePerUnit))))
                                                .Add(new BsonDocument()
                                                     .Add(new BsonElement(nameof(PurchaseOrderLine.ProductId), BsonString.Create(@event.Lines.ElementAt(1).ProductId.ToString())))
                                                     .Add(new BsonElement(nameof(PurchaseOrderLine.Quantity), BsonDecimal128.Create(@event.Lines.ElementAt(1).Quantity)))
                                                     .Add(new BsonElement(nameof(PurchaseOrderLine.Measure), BsonString.Create(@event.Lines.ElementAt(1).Measure)))
                                                     .Add(new BsonElement(nameof(PurchaseOrderLine.PricePerUnit), BsonDecimal128.Create(@event.Lines.ElementAt(1).PricePerUnit))))));

            // Mock up a mongo client for the mongo db event store.
            BsonDocument actual     = null;
            var          collection = Mock.Create <IMongoCollection <BsonDocument> >();

            Mock.Arrange(() => collection.InsertOne(Arg.IsAny <BsonDocument>(), Arg.IsAny <InsertOneOptions>(), Arg.IsAny <CancellationToken>()))
            .DoInstead((BsonDocument document) => actual = document);
            var database = Mock.Create <IMongoDatabase>();

            Mock.Arrange(() => database.GetCollection <BsonDocument>(Arg.AnyString, Arg.IsAny <MongoCollectionSettings>()))
            .Returns(collection);
            var client = Mock.Create <IMongoClient>();

            Mock.Arrange(() => client.GetDatabase(Arg.AnyString, Arg.IsAny <MongoDatabaseSettings>()))
            .Returns(database);

            /// Act
            // Save the event.
            MongoDBEventStore.Save(client, nextId, @event);

            /// Assert
            // Verify that the actual document matches the expected document.
            Assert.Equal(expected, actual);
        }