Inheritance: IDisposable
示例#1
0
        public MongoMetadata(string connectionString, MongoConfiguration.Metadata metadata = null)
        {
            this.connectionString = connectionString;
            this.Configuration = metadata ?? MongoConfiguration.Metadata.Default;
            lock (MetadataCache)
            {
                MongoMetadataCache metadataCache;
                MetadataCache.TryGetValue(this.connectionString, out metadataCache);
                if (metadataCache == null)
                {
                    metadataCache = new MongoMetadataCache
                                        {
                                            DspMetadata = new DSPMetadata(ContainerName, RootNamespace),
                                            ProviderTypes = new Dictionary<string, Type>()
                                        };
                    MetadataCache.Add(this.connectionString, metadataCache);
                }
                this.dspMetadata = metadataCache.DspMetadata;
                this.providerTypes = metadataCache.ProviderTypes;
            }

            using (var context = new MongoContext(connectionString))
            {
                PopulateMetadata(context);
            }
        }
示例#2
0
        public MongoMetadata(string connectionString, MongoConfiguration.Metadata metadata = null)
        {
            _connectionString = connectionString;
            this.Configuration = metadata ?? MongoConfiguration.Metadata.Default;

            lock (s_metadataCache)
            {
                _instanceMetadataCache = GetOrCreateMetadataCache();
            }

            var context = new MongoContext(connectionString);
            PopulateMetadata(context);
        }
        public override void SaveChanges()
        {
            base.SaveChanges();

            MongoContext mongoContext = new MongoContext(_connectionString);

            foreach (var pendingChange in _pendingChanges)
            {
                var action = pendingChange.Action;
                action(mongoContext, pendingChange);
            }

            _pendingChanges.Clear();
        }
        public override void SaveChanges()
        {
            base.SaveChanges();

            using (MongoContext mongoContext = new MongoContext(connectionString))
            {
                foreach (var pendingChange in this.pendingChanges)
                {
                    var action = pendingChange.Action;
                    action(mongoContext, pendingChange);
                }
            }

            this.pendingChanges.Clear();
        }
示例#5
0
 private ResourceSet AddResourceSet(MongoContext context, string collectionName, BsonDocument document = null)
 {
     AddDocumentType(context, collectionName, document, ResourceTypeKind.EntityType);
     return _instanceMetadataCache.ResolveResourceSet(collectionName);
 }
示例#6
0
        private void PopulateMetadata(MongoContext context)
        {
            foreach (var collectionName in GetCollectionNames(context))
            {
                var collection = context.Database.GetCollection(collectionName);
                var resourceSet = this.dspMetadata.ResourceSets.SingleOrDefault(x => x.Name == collectionName);

                var documents = collection.FindAll();
                if (this.Configuration.PrefetchRows == 0)
                {
                    if (resourceSet == null)
                    {
                        RegisterResourceSet(context, collectionName);
                    }
                }
                else
                {
                    int rowCount = 0;
                    foreach (var document in documents)
                    {
                        if (resourceSet == null)
                        {
                            resourceSet = RegisterResourceSet(context, collectionName, document);
                        }
                        else
                        {
                            UpdateResourceSet(context, resourceSet, document);
                        }

                        ++rowCount;
                        if (this.Configuration.PrefetchRows >= 0 && rowCount >= this.Configuration.PrefetchRows)
                            break;
                    }
                }
            }
        }
 private void RemoveDocument(MongoContext mongoContext, ResourceChange change)
 {
     var collection = mongoContext.Database.GetCollection(change.CollectionName);
     var query = Query.EQ(MongoMetadata.ProviderObjectIdName, ObjectId.Parse(change.Resource.GetValue(MongoMetadata.MappedObjectIdName).ToString()));
     collection.Remove(query);
 }
示例#8
0
 private void RegisterDocumentProperty(MongoContext context, ResourceType resourceType, BsonElement element)
 {
     var resourceProperty = ResolveResourceProperty(resourceType, element);
     if (resourceProperty == null)
     {
         RegisterResourceProperty(context, resourceType, element);
     }
     else if ((resourceProperty.Kind & ResourcePropertyKind.ComplexType) != 0 && element.Value != BsonNull.Value)
     {
         RegisterDocumentProperties(context, resourceType, element);
     }
     else if ((resourceProperty.Kind & ResourcePropertyKind.Collection) != 0 && element.Value != BsonNull.Value)
     {
         RegisterArrayProperty(context, resourceType, element);
     }
 }
示例#9
0
        private void RegisterArrayProperty(MongoContext context, ResourceType collectionType, BsonElement element)
        {
            var propertyName = GetResourcePropertyName(element, ResourceTypeKind.EntityType);
            var bsonArray = element.Value.AsBsonArray;
            if (bsonArray != null)
            {
                foreach (var arrayValue in bsonArray)
                {
                    if (arrayValue.AsBsonValue == BsonNull.Value)
                        continue;

                    if (arrayValue.BsonType == BsonType.Document)
                    {
                        RegisterDocumentProperties(context, collectionType, new BsonElement(element.Name, arrayValue));
                    }
                    else if (ResolveResourceProperty(collectionType, propertyName) == null)
                    {
                        // OData protocol doesn't support collections of collections
                        if (arrayValue.BsonType != BsonType.Array)
                        {
                            var mappedType = BsonTypeMapper.MapToDotNetValue(arrayValue).GetType();
                            _instanceMetadataCache.AddCollectionProperty(collectionType, propertyName, mappedType);
                        }
                    }
                }
            }
        }
        private void UpdateDocument(MongoContext mongoContext, ResourceChange change)
        {
            if (!change.ModifiedProperties.Any())
                return;

            var collection = mongoContext.Database.GetCollection<BsonDocument>(change.CollectionName);
            var filter = Builders<BsonDocument>.Filter.Eq(MongoMetadata.ProviderObjectIdName, ObjectId.Parse(change.Resource.GetValue(MongoMetadata.MappedObjectIdName).ToString()));

            UpdateDefinition<BsonDocument> update = null;

            foreach (var resourceProperty in change.ModifiedProperties)
            {
                if (update == null)
                {
                    if (resourceProperty.Value != null)
                    {
                        update = Builders<BsonDocument>.Update.Set(resourceProperty.Key, BsonValue.Create(resourceProperty.Value));
                    }
                    else
                    {
                        update = Builders<BsonDocument>.Update.Unset(resourceProperty.Key);
                    }
                }
                else
                {
                    if (resourceProperty.Value != null)
                    {
                        update = update.Set(resourceProperty.Key, BsonValue.Create(resourceProperty.Value));
                    }
                    else
                    {
                        update = update.Unset(resourceProperty.Key);
                    }
                }
            }

            collection.UpdateOneAsync(filter, update).GetAwaiter().GetResult();
        }
 private void RemoveDocument(MongoContext mongoContext, ResourceChange change)
 {
     var collection = mongoContext.Database.GetCollection<BsonDocument>(change.CollectionName);
     var filter = Builders<BsonDocument>.Filter.Eq(MongoMetadata.ProviderObjectIdName, ObjectId.Parse(change.Resource.GetValue(MongoMetadata.MappedObjectIdName).ToString()));
     collection.DeleteOneAsync(filter).GetAwaiter().GetResult();
 }
示例#12
0
 private void UpdateResourceSet(MongoContext context, ResourceSet resourceSet, BsonDocument document)
 {
     foreach (var element in document.Elements)
     {
         var propertyName = GetResourcePropertyName(element);
         var resourceProperty = resourceSet.ResourceType.Properties.Where(x => x.Name == propertyName).SingleOrDefault();
         if (resourceProperty == null)
         {
             var elementType = GetElementType(element);
             RegisterResourceProperty(context, resourceSet.Name, resourceSet.ResourceType, elementType, element, ResourceTypeKind.EntityType);
         }
     }
 }
示例#13
0
 private ResourceSet RegisterResourceSet(MongoContext context, string collectionName, BsonDocument document = null)
 {
     RegisterResourceType(context, collectionName, document, ResourceTypeKind.EntityType);
     return this.dspMetadata.ResourceSets.SingleOrDefault(x => x.Name == collectionName);
 }
示例#14
0
        private void RegisterResourceProperty(MongoContext context, string collectionName, ResourceType collectionType,
            Type elementType, BsonElement element, ResourceTypeKind resourceTypeKind)
        {
            if (ResolveProviderType(element.Value) == null)
                return;

            string propertyName = element.Name;
            var propertyValue = element.Value;
            var isKey = false;
            if (IsObjectId(element))
            {
                propertyName = MongoMetadata.MappedObjectIdName;
                if (resourceTypeKind == ResourceTypeKind.EntityType)
                    this.dspMetadata.AddKeyProperty(collectionType, propertyName, elementType);
                else
                    this.dspMetadata.AddPrimitiveProperty(collectionType, propertyName, elementType);
                isKey = true;
            }
            else if (elementType == typeof(BsonDocument))
            {
                ResourceType resourceType = null;
                var resourceSet = this.dspMetadata.ResourceSets.SingleOrDefault(x => x.Name == propertyName);
                if (resourceSet != null)
                {
                    resourceType = resourceSet.ResourceType;
                }
                else
                {
                    resourceType = RegisterResourceType(context, GetComplexTypeName(collectionName, propertyName),
                                                        element.Value.AsBsonDocument, ResourceTypeKind.ComplexType);
                }
                this.dspMetadata.AddComplexProperty(collectionType, propertyName, resourceType);
            }
            else if (elementType == typeof(BsonArray))
            {
                var bsonArray = element.Value.AsBsonArray;
                if (bsonArray != null && bsonArray.Count > 0)
                {
                    var arrayElement = bsonArray.First();
                    if (arrayElement.BsonType == BsonType.Document)
                    {
                        ResourceType resourceType = null;
                        var resourceSet = this.dspMetadata.ResourceSets.SingleOrDefault(x => x.Name == propertyName);
                        if (resourceSet != null)
                        {
                            resourceType = resourceSet.ResourceType;
                        }
                        else
                        {
                            resourceType = RegisterResourceType(context, GetCollectionTypeName(collectionName, propertyName),
                                                                arrayElement.AsBsonDocument, ResourceTypeKind.ComplexType);
                        }
                        this.dspMetadata.AddCollectionProperty(collectionType, propertyName, resourceType);
                    }
                    else
                    {
                        this.dspMetadata.AddCollectionProperty(collectionType, propertyName, arrayElement.RawValue.GetType());
                    }
                }
            }
            else
            {
                this.dspMetadata.AddPrimitiveProperty(collectionType, propertyName, elementType);
            }

            if (!string.IsNullOrEmpty(propertyName))
            {
                AddProviderType(collectionName, propertyName, propertyValue, isKey);
            }
        }
示例#15
0
 private IEnumerable<string> GetCollectionNames(MongoContext context)
 {
     var collectionNamesCursor = context.Database.ListCollectionsAsync().GetAwaiter().GetResult();
     var collections = collectionNamesCursor.ToListAsync().GetAwaiter().GetResult();
     var collectionNames = collections.Select(y => y["name"].AsString).Where(x => !x.StartsWith("system."));
     return collectionNames;
 }
示例#16
0
 private IEnumerable<string> GetCollectionNames(MongoContext context)
 {
     return context.Database.GetCollectionNames().Where(x => !x.StartsWith("system."));
 }
示例#17
0
        private void PopulateMetadata(MongoContext context)
        {
            var collectionNames = GetCollectionNames(context);
            lock (_instanceMetadataCache)
            {
                foreach (var collectionName in collectionNames)
                {
                    var resourceSet = _instanceMetadataCache.ResolveResourceSet(collectionName);

                    if (this.Configuration.PrefetchRows == 0)
                    {
                        if (resourceSet == null)
                        {
                            AddResourceSet(context, collectionName);
                        }
                    }
                    else
                    {
                        PopulateMetadataFromCollection(context, collectionName, resourceSet);
                    }
                }

                foreach (var prop in _unresolvedProperties)
                {
                    var providerType = typeof(string);
                    var propertyName = NormalizeResourcePropertyName(prop.PropertyName);
                    _instanceMetadataCache.AddPrimitiveProperty(prop.CollectionType, propertyName, providerType);
                    _instanceMetadataCache.ProviderTypes.Add(
                        GetQualifiedPropertyName(prop.CollectionType.Name, propertyName), providerType);
                }
            }
        }
示例#18
0
        private void PopulateMetadataFromCollection(MongoContext context, string collectionName, ResourceSet resourceSet)
        {
            var collection = context.Database.GetCollection(collectionName);
            const string naturalSort = "$natural";
            var sortOrder = this.Configuration.FetchPosition == MongoConfiguration.FetchPosition.End
                                ? SortBy.Descending(naturalSort)
                                : SortBy.Ascending(naturalSort);
            var documents = collection.FindAll().SetSortOrder(sortOrder);

            int rowCount = 0;
            foreach (var document in documents)
            {
                if (resourceSet == null)
                {
                    resourceSet = AddResourceSet(context, collectionName, document);
                }
                else
                {
                    UpdateResourceSet(context, resourceSet, document);
                }

                ++rowCount;
                if (this.Configuration.PrefetchRows >= 0 && rowCount >= this.Configuration.PrefetchRows)
                    break;
            }
        }
示例#19
0
        private void PopulateMetadataFromCollection(MongoContext context, string collectionName, ResourceSet resourceSet)
        {
            var collection = context.Database.GetCollection<BsonDocument>(collectionName);
            const string naturalSort = "$natural";
            var sortBuilder = Builders<BsonDocument>.Sort;
            var sort = this.Configuration.FetchPosition == MongoConfiguration.FetchPosition.End
                                ? sortBuilder.Descending(naturalSort)
                                : sortBuilder.Ascending(naturalSort);
            var documents = collection.Find(new BsonDocument()).Sort(sort).ToListAsync().GetAwaiter().GetResult();
            int rowCount = 0;
            foreach (var document in documents)
            {
                if (resourceSet == null)
                {
                    resourceSet = AddResourceSet(context, collectionName, document);
                }
                else
                {
                    UpdateResourceSet(context, resourceSet, document);
                }

                ++rowCount;
                if (this.Configuration.PrefetchRows >= 0 && rowCount >= this.Configuration.PrefetchRows)
                    break;
            }
        }
示例#20
0
        internal void RegisterResourceProperty(MongoContext context, ResourceType resourceType, BsonElement element)
        {
            var collectionProperty = new CollectionProperty { CollectionType = resourceType, PropertyName = element.Name };
            var resourceProperty = ResolveResourceProperty(resourceType, element);
            if (resourceProperty == null)
            {
                lock (_unresolvedProperties)
                {
                    var unresolvedEarlier = _unresolvedProperties.Contains(collectionProperty);
                    var resolvedNow = ResolveProviderType(element.Value, IsObjectId(element)) != null;

                    if (!unresolvedEarlier && !resolvedNow)
                        _unresolvedProperties.Add(collectionProperty);
                    else if (unresolvedEarlier && resolvedNow)
                        _unresolvedProperties.Remove(collectionProperty);

                    if (resolvedNow)
                    {
                        AddResourceProperty(context, resourceType.Name, resourceType, element, resourceType.ResourceTypeKind == ResourceTypeKind.EntityType);
                    }
                }
            }
        }
示例#21
0
 private void RegisterDocumentProperties(MongoContext context, ResourceType collectionType, BsonElement element)
 {
     var resourceName = GetResourcePropertyName(element, ResourceTypeKind.EntityType);
     var resourceType = ResolveResourceType(resourceName, collectionType.Name);
     if (resourceType == null)
     {
         AddDocumentProperty(context, collectionType.Name, collectionType, resourceName, element, true);
     }
     else
     {
         foreach (var documentElement in element.Value.AsBsonDocument.Elements)
         {
             RegisterDocumentProperty(context, resourceType, documentElement);
         }
     }
 }
示例#22
0
 private void AddDocumentProperty(MongoContext context, string collectionName, ResourceType collectionType, string propertyName, BsonElement element, bool isCollection = false)
 {
     ResourceType resourceType = null;
     var resourceSet = _instanceMetadataCache.ResolveResourceSet(collectionName);
     if (resourceSet != null)
     {
         resourceType = resourceSet.ResourceType;
     }
     else
     {
         resourceType = AddDocumentType(context, GetQualifiedTypeName(collectionName, propertyName),
                                             element.Value.AsBsonDocument, ResourceTypeKind.ComplexType);
     }
     if (isCollection && ResolveResourceProperty(collectionType, propertyName) == null)
         _instanceMetadataCache.AddCollectionProperty(collectionType, propertyName, resourceType);
     else
         _instanceMetadataCache.AddComplexProperty(collectionType, propertyName, resourceType);
 }
示例#23
0
 private void UpdateResourceSet(MongoContext context, ResourceSet resourceSet, BsonDocument document)
 {
     foreach (var element in document.Elements)
     {
         RegisterDocumentProperty(context, resourceSet.ResourceType, element);
     }
 }
示例#24
0
        private ResourceType AddDocumentType(MongoContext context, string collectionName, BsonDocument document, ResourceTypeKind resourceTypeKind)
        {
            var collectionType = resourceTypeKind == ResourceTypeKind.EntityType
                                     ? _instanceMetadataCache.AddEntityType(collectionName)
                                     : _instanceMetadataCache.AddComplexType(collectionName);

            bool hasObjectId = false;
            if (document != null)
            {
                foreach (var element in document.Elements)
                {
                    RegisterResourceProperty(context, collectionType, element);
                    if (IsObjectId(element))
                        hasObjectId = true;
                }
            }

            if (!hasObjectId)
            {
                if (resourceTypeKind == ResourceTypeKind.EntityType)
                {
                    _instanceMetadataCache.AddKeyProperty(collectionType, MappedObjectIdName, MappedObjectIdType);
                }
                AddProviderType(collectionName, ProviderObjectIdName, BsonObjectId.Empty, true);
            }

            if (resourceTypeKind == ResourceTypeKind.EntityType)
                _instanceMetadataCache.AddResourceSet(collectionName, collectionType);

            return collectionType;
        }
示例#25
0
        private void UpdateDocument(MongoContext mongoContext, ResourceChange change)
        {
            if (!change.ModifiedProperties.Any())
                return;

            var collection = mongoContext.Database.GetCollection(change.CollectionName);
            var query = Query.EQ(MongoMetadata.ProviderObjectIdName, ObjectId.Parse(change.Resource.GetValue(MongoMetadata.MappedObjectIdName).ToString()));
            UpdateBuilder update = null;

            foreach (var resourceProperty in change.ModifiedProperties)
            {
                if (update == null)
                {
                    if (resourceProperty.Value != null)
                        update = Update.Set(resourceProperty.Key, BsonValue.Create(resourceProperty.Value));
                    else
                        update = Update.Unset(resourceProperty.Key);
                }
                else
                {
                    if (resourceProperty.Value != null)
                        update = update.Set(resourceProperty.Key, BsonValue.Create(resourceProperty.Value));
                    else
                        update = update.Unset(resourceProperty.Key);
                }
            }

            collection.Update(query, update);
        }
示例#26
0
        private void AddResourceProperty(MongoContext context, string collectionName, ResourceType collectionType,
            BsonElement element, bool treatObjectIdAsKey = false)
        {
            var elementType = GetElementType(element, treatObjectIdAsKey);
            var propertyName = GetResourcePropertyName(element, collectionType.ResourceTypeKind);
            var propertyValue = element.Value;

            if (string.IsNullOrEmpty(propertyName))
                return;

            var isKey = false;
            if (IsObjectId(element))
            {
                if (treatObjectIdAsKey)
                    _instanceMetadataCache.AddKeyProperty(collectionType, propertyName, elementType);
                else
                    _instanceMetadataCache.AddPrimitiveProperty(collectionType, propertyName, elementType);
                isKey = true;
            }
            else if (elementType == typeof(BsonDocument))
            {
                AddDocumentProperty(context, collectionName, collectionType, propertyName, element);
            }
            else if (elementType == typeof(BsonArray))
            {
                RegisterArrayProperty(context, collectionType, element);
            }
            else
            {
                _instanceMetadataCache.AddPrimitiveProperty(collectionType, propertyName, elementType);
            }

            if (!string.IsNullOrEmpty(propertyName))
            {
                AddProviderType(collectionName, IsObjectId(element) ? ProviderObjectIdName : propertyName, propertyValue, isKey);
            }
        }
示例#27
0
 private void InsertDocument(MongoContext mongoContext, ResourceChange change)
 {
     var collection = mongoContext.Database.GetCollection(change.CollectionName);
     var document = MongoDSPConverter.CreateBSonDocument(change.Resource, this.mongoMetadata, change.CollectionName);
     collection.Insert(document);
     change.Resource.SetValue(MongoMetadata.MappedObjectIdName, document.GetValue(MongoMetadata.ProviderObjectIdName).ToString());
 }
示例#28
0
 internal void UpdateResourceType(MongoContext context, ResourceType resourceType, BsonElement element)
 {
     var elementType = GetElementType(element);
     RegisterResourceProperty(context, resourceType.Name, resourceType, elementType, element, ResourceTypeKind.EntityType);
 }