/// <summary>
        /// Set new Id in entity class if entity needs one
        /// </summary>
        public virtual void SetAutoId(object entity, LiteEngine engine, string collection)
        {
            if (entity == null)
            {
                throw new ArgumentNullException("entity");
            }
            if (engine == null)
            {
                throw new ArgumentNullException("engine");
            }
            if (collection.IsNullOrWhiteSpace())
            {
                throw new ArgumentNullException("collection");
            }

            // if object is BsonDocument, add _id as ObjectId
            if (entity is BsonDocument)
            {
                var doc = entity as BsonDocument;
                if (!doc.RawValue.ContainsKey("_id"))
                {
                    doc["_id"] = ObjectId.NewObjectId();
                }
                return;
            }

            // get fields mapper
            var mapper = this.GetEntityMapper(entity.GetType());

            var id = mapper.Id;

            // if not id or no autoId = true
            if (id == null || id.AutoId == false)
            {
                return;
            }

            AutoId autoId;

            if (_autoId.TryGetValue(id.DataType, out autoId))
            {
                var value = id.Getter(entity);

                if (value == null || autoId.IsEmpty(value) == true)
                {
                    var newId = autoId.NewId(engine, collection);

                    id.Setter(entity, newId);
                }
            }
        }
        public BsonMapper(Func <Type, object> customTypeInstantiator = null)
        {
            this.SerializeNullValues   = false;
            this.TrimWhitespace        = true;
            this.EmptyStringToNull     = true;
            this.ResolveFieldName      = (s) => s;
            this.ResolveMember         = (t, mi, mm) => { };
            this.ResolveCollectionName = (t) => Reflection.IsList(t) ? Reflection.GetListItemType(t).Name : t.Name;

#if NET35
            this.IncludeFields = false;
#endif

            _typeInstantiator = customTypeInstantiator ?? Reflection.CreateInstance;

            #region Register CustomTypes

            RegisterType <Uri>(uri => uri.AbsoluteUri, bson => new Uri(bson.AsString));
            RegisterType <DateTimeOffset>(value => new BsonValue(value.UtcDateTime), bson => bson.AsDateTime.ToUniversalTime());
            RegisterType <TimeSpan>(value => new BsonValue(value.Ticks), bson => new TimeSpan(bson.AsInt64));

            #endregion Register CustomTypes

            #region Register AutoId

            // register AutoId for ObjectId, Guid and Int32
            RegisterAutoId
            (
                value => value.Equals(ObjectId.Empty),
                (db, col) => ObjectId.NewObjectId()
            );

            RegisterAutoId
            (
                value => value == Guid.Empty,
                (db, col) => Guid.NewGuid()
            );

            RegisterAutoId
            (
                value => value == 0,
                (db, col) =>
            {
                var max = db.Max(col, "_id");
                return(max.IsMaxValue ? 1 : (max + 1));
            }
            );

            #endregion
        }
Exemple #3
0
        /// <summary>
        /// Internal implementation of insert a document
        /// </summary>
        private void InsertDocument(CollectionPage col, BsonDocument doc)
        {
            BsonValue id;

            // if no _id, add one as ObjectId
            if (!doc.RawValue.TryGetValue("_id", out id))
            {
                doc["_id"] = id = ObjectId.NewObjectId();
            }

            // test if _id is a valid type
            if (id.IsNull || id.IsMinValue || id.IsMaxValue)
            {
                throw LiteException.InvalidDataType("_id", id);
            }

            _log.Write(Logger.COMMAND, "insert document on '{0}' :: _id = {1}", col.CollectionName, id);

            // serialize object
            var bytes = BsonSerializer.Serialize(doc);

            // storage in data pages - returns dataBlock address
            var dataBlock = _data.Insert(col, bytes);

            // store id in a PK index [0 array]
            var pk = _indexer.AddNode(col.PK, id, null);

            // do link between index <-> data block
            pk.DataBlock = dataBlock.Position;

            // for each index, insert new IndexNode
            foreach (var index in col.GetIndexes(false))
            {
                // for each index, get all keys (support now multi-key) - gets distinct values only
                // if index are unique, get single key only
                var keys = doc.GetValues(index.Field, index.Unique);

                // do a loop with all keys (multi-key supported)
                foreach (var key in keys)
                {
                    // insert node
                    var node = _indexer.AddNode(index, key, pk);

                    // link my index node to data block address
                    node.DataBlock = dataBlock.Position;
                }
            }
        }
Exemple #4
0
        /// <summary>
        /// Set new Id in entity class if entity needs one
        /// </summary>
        public void SetAutoId(T document)
        {
            // if object is BsonDocument, add _id as ObjectId
            if (document is BsonDocument)
            {
                var doc = document as BsonDocument;
                if (!doc.RawValue.ContainsKey("_id"))
                {
                    doc["_id"] = ObjectId.NewObjectId();
                }
                return;
            }

            // get fields mapper
            var mapper = _mapper.GetPropertyMapper(document.GetType());

            // it's not best way because is scan all properties - but Id propably is first field :)
            var id = mapper.Select(x => x.Value).FirstOrDefault(x => x.FieldName == "_id");

            // if not id or no autoId = true
            if (id == null || id.AutoId == false)
            {
                return;
            }

            // get id value
            var value = id.Getter(document);

            // test for ObjectId, Guid and Int32 types
            if (id.PropertyType == typeof(ObjectId) && (value == null || ObjectId.Empty.Equals((ObjectId)value)))
            {
                id.Setter(document, ObjectId.NewObjectId());
            }
            else if (id.PropertyType == typeof(Guid) && Guid.Empty.Equals((Guid)value))
            {
                id.Setter(document, Guid.NewGuid());
            }
            else if (id.PropertyType == typeof(Int32) && ((Int32)value) == 0)
            {
                var max = this.Max();
                id.Setter(document, max.IsMaxValue ? 1 : max + 1);
            }
        }
Exemple #5
0
        public BsonMapper()
        {
            this.SerializeNullValues = false;
            this.TrimWhitespace      = true;
            this.EmptyStringToNull   = true;
            this.ResolvePropertyName = (s) => s;

            #region Register CustomTypes

            RegisterType(uri => uri.AbsoluteUri, bson => new Uri(bson.AsString));
            RegisterType <DateTimeOffset>(value => new BsonValue(value.UtcDateTime), bson => bson.AsDateTime.ToUniversalTime());
            RegisterType <TimeSpan>(value => new BsonValue(value.Ticks), bson => new TimeSpan(bson.AsInt64));

            #endregion Register CustomTypes

            #region Register AutoId

            // register AutoId for ObjectId, Guid and Int32
            RegisterAutoId
            (
                v => v.Equals(ObjectId.Empty),
                c => ObjectId.NewObjectId()
            );

            RegisterAutoId
            (
                v => v == Guid.Empty,
                c => Guid.NewGuid()
            );

            RegisterAutoId
            (
                v => v == 0,
                c =>
            {
                var max = c.Max();
                return(max.IsMaxValue ? 1 : (max + 1));
            }
            );

            #endregion
        }
Exemple #6
0
        /// <summary>
        /// Set new Id in entity class if entity needs one
        /// </summary>
        public void SetAutoId(object entity, LiteCollection <BsonDocument> col)
        {
            // if object is BsonDocument, add _id as ObjectId
            if (entity is BsonDocument)
            {
                var doc = entity as BsonDocument;
                if (!doc.RawValue.ContainsKey("_id"))
                {
                    doc["_id"] = ObjectId.NewObjectId();
                }
                return;
            }

            // get fields mapper
            var mapper = GetPropertyMapper(entity.GetType());

            // it's not best way because is scan all properties - but Id propably is first field :)
            var id = mapper.Select(x => x.Value).FirstOrDefault(x => x.FieldName == "_id");

            // if not id or no autoId = true
            if (id == null || id.AutoId == false)
            {
                return;
            }

            AutoId autoId;

            if (_autoId.TryGetValue(id.PropertyType, out autoId))
            {
                var value = id.Getter(entity);

                if (value == null || autoId.IsEmpty(value) == true)
                {
                    var newId = autoId.NewId(col);

                    id.Setter(entity, newId);
                }
            }
        }
Exemple #7
0
        /// <summary>
        /// Set new Id in entity class if entity needs one
        /// </summary>
        public virtual void SetAutoId(object entity, LiteCollection <BsonDocument> col)
        {
            // if object is BsonDocument, add _id as ObjectId
            if (entity is BsonDocument)
            {
                var doc = entity as BsonDocument;
                if (!doc.RawValue.ContainsKey("_id"))
                {
                    doc["_id"] = ObjectId.NewObjectId();
                }
                return;
            }

            // get fields mapper
            var mapper = this.GetEntityMapper(entity.GetType());

            var id = mapper.Id;

            // if not id or no autoId = true
            if (id == null || id.AutoId == false)
            {
                return;
            }

            AutoId autoId;

            if (_autoId.TryGetValue(id.DataType, out autoId))
            {
                var value = id.Getter(entity);

                if (value == null || autoId.IsEmpty(value) == true)
                {
                    var newId = autoId.NewId(col);

                    id.Setter(entity, newId);
                }
            }
        }
Exemple #8
0
        public BsonMapper()
        {
            this.SerializeNullValues = false;
            this.TrimWhitespace      = true;
            this.EmptyStringToNull   = true;
            this.ResolvePropertyName = (s) => s;

            // register custom types
            this.RegisterType <Uri>
            (
                serialize: (uri) => uri.AbsoluteUri,
                deserialize: (bson) => new Uri(bson.AsString)
            );

            // register AutoId for ObjectId, Guid and Int32
            this.RegisterAutoId <ObjectId>
            (
                isEmpty: (v) => v.Equals(ObjectId.Empty),
                newId: (c) => ObjectId.NewObjectId()
            );

            this.RegisterAutoId <Guid>
            (
                isEmpty: (v) => v == Guid.Empty,
                newId: (c) => Guid.NewGuid()
            );

            this.RegisterAutoId <Int32>
            (
                isEmpty: (v) => v == 0,
                newId: (c) =>
            {
                var max = c.Max();
                return(max.IsMaxValue ? 1 : (max + 1));
            }
            );
        }
Exemple #9
0
 /// <summary>
 /// Create a new OBJECTID value
 /// </summary>
 public static IEnumerable <BsonValue> OBJECTID()
 {
     yield return(ObjectId.NewObjectId());
 }
Exemple #10
0
 public static BsonValue OBJECTID() => ObjectId.NewObjectId();
Exemple #11
0
        /// <summary>
        /// Internal implementation of insert a document
        /// </summary>
        private void InsertDocument(CollectionPage col, BsonDocument doc, BsonType autoId)
        {
            // collection Sequence was created after release current datafile version.
            // In this case, Sequence will be 0 but already has documents. Let's fix this
            // ** this code can be removed when datafile change from 7 (HeaderPage.FILE_VERSION) **
            if (col.Sequence == 0 && col.DocumentCount > 0)
            {
                var max = this.Max(col.CollectionName, "_id");

                // if max value is a number, convert to Sequence last value
                // if not, just set sequence as document count
                col.Sequence = (max.IsInt32 || max.IsInt64 || max.IsDouble || max.IsDecimal) ?
                               Convert.ToInt64(max.RawValue) :
                               Convert.ToInt64(col.DocumentCount);
            }

            // increase collection sequence _id
            col.Sequence++;

            _pager.SetDirty(col);

            // if no _id, add one
            if (!doc.RawValue.TryGetValue("_id", out var id))
            {
                doc["_id"] = id =
                    autoId == BsonType.ObjectId ? new BsonValue(ObjectId.NewObjectId()) :
                    autoId == BsonType.Guid ? new BsonValue(Guid.NewGuid()) :
                    autoId == BsonType.DateTime ? new BsonValue(DateTime.Now) :
                    autoId == BsonType.Int32 ? new BsonValue((Int32)col.Sequence) :
                    autoId == BsonType.Int64 ? new BsonValue(col.Sequence) : BsonValue.Null;
            }
            // create bubble in sequence number if _id is bigger than current sequence
            else if (autoId == BsonType.Int32 || autoId == BsonType.Int64)
            {
                var current = id.AsInt64;

                // if current id is bigger than sequence, jump sequence to this number. Other was, do not increse sequnce
                col.Sequence = current >= col.Sequence ? current : col.Sequence - 1;
            }

            // test if _id is a valid type
            if (id.IsNull || id.IsMinValue || id.IsMaxValue)
            {
                throw LiteException.InvalidDataType("_id", id);
            }

            _log.Write(Logger.COMMAND, "insert document on '{0}' :: _id = {1}", col.CollectionName, id.RawValue);

            // serialize object
            var bytes = _bsonWriter.Serialize(doc);

            // storage in data pages - returns dataBlock address
            var dataBlock = _data.Insert(col, bytes);

            // store id in a PK index [0 array]
            var pk = _indexer.AddNode(col.PK, id, null);

            // do link between index <-> data block
            pk.DataBlock = dataBlock.Position;

            // for each index, insert new IndexNode
            foreach (var index in col.GetIndexes(false))
            {
                // for each index, get all keys (support now multi-key) - gets distinct values only
                // if index are unique, get single key only
                var expr = new BsonExpression(index.Expression);
                var keys = expr.Execute(doc, true);

                // do a loop with all keys (multi-key supported)
                foreach (var key in keys)
                {
                    // insert node
                    var node = _indexer.AddNode(index, key, pk);

                    // link my index node to data block address
                    node.DataBlock = dataBlock.Position;
                }
            }
        }
Exemple #12
0
        public BsonMapper()
        {
            this.SerializeNullValues = false;
            this.TrimWhitespace      = true;
            this.EmptyStringToNull   = true;
            this.ResolvePropertyName = (s) => s;

            // register custom types
            this.RegisterType <Uri>
            (
                serialize: (uri) => uri.AbsoluteUri,
                deserialize: (bson) => new Uri(bson.AsString)
            );

            this.RegisterType <NameValueCollection>
            (
                serialize: (nv) =>
            {
                var doc = new BsonDocument();

                foreach (var key in nv.AllKeys)
                {
                    doc[key] = nv[key];
                }

                return(doc);
            },
                deserialize: (bson) =>
            {
                var nv  = new NameValueCollection();
                var doc = bson.AsDocument;

                foreach (var key in doc.Keys)
                {
                    nv[key] = doc[key].AsString;
                }

                return(nv);
            }
            );

            // register AutoId for ObjectId, Guid and Int32
            this.RegisterAutoId <ObjectId>
            (
                isEmpty: (v) => v.Equals(ObjectId.Empty),
                newId: (c) => ObjectId.NewObjectId()
            );

            this.RegisterAutoId <Guid>
            (
                isEmpty: (v) => v == Guid.Empty,
                newId: (c) => Guid.NewGuid()
            );

            this.RegisterAutoId <Int32>
            (
                isEmpty: (v) => v == 0,
                newId: (c) =>
            {
                var max = c.Max();
                return(max.IsMaxValue ? 1 : (max + 1));
            }
            );
        }
Exemple #13
0
        /// <summary>
        /// Insert a new document to this collection. Document Id must be a new value in collection - Returns document Id
        /// </summary>
        public virtual BsonValue Insert(T document)
        {
            if (document == null)
            {
                throw new ArgumentNullException("document");
            }

            this.Database.Mapper.SetAutoId(document, this.GetBsonCollection());

            var doc = this.Database.Mapper.ToDocument(document);

            BsonValue id;

            // add ObjectId to _id if _id not found
            if (!doc.RawValue.TryGetValue("_id", out id))
            {
                id = doc["_id"] = ObjectId.NewObjectId();
            }

            // test if _id is a valid type
            if (id.IsNull || id.IsMinValue || id.IsMaxValue)
            {
                throw LiteException.InvalidDataType("_id", id);
            }

            // serialize object
            var bytes = BsonSerializer.Serialize(doc);

            this.Database.Transaction.Begin();

            try
            {
                var col = this.GetCollectionPage(true);

                // storage in data pages - returns dataBlock address
                var dataBlock = this.Database.Data.Insert(col, bytes);

                // store id in a PK index [0 array]
                var pk = this.Database.Indexer.AddNode(col.PK, id);

                // do links between index <-> data block
                pk.DataBlock          = dataBlock.Position;
                dataBlock.IndexRef[0] = pk.Position;

                // for each index, insert new IndexNode
                foreach (var index in col.GetIndexes(false))
                {
                    var key = doc.Get(index.Field);

                    var node = this.Database.Indexer.AddNode(index, key);

                    // point my index to data object
                    node.DataBlock = dataBlock.Position;

                    // point my dataBlock
                    dataBlock.IndexRef[index.Slot] = node.Position;
                }

                this.Database.Transaction.Commit();

                return(id);
            }
            catch
            {
                this.Database.Transaction.Rollback();
                throw;
            }
        }