/// <summary> /// Creates entity relation /// </summary> /// <param name="entity"></param> public bool Create(IStorageEntityRelation entityRelation) { if (entityRelation == null) { throw new ArgumentNullException("entityRelation"); } var mongoEntityRelation = entityRelation as MongoEntityRelation; if (mongoEntityRelation == null) { throw new Exception("The specified entityRelation is not mongo storage object."); } MongoTransaction transaction = null; if (!MongoStaticContext.Context.TransactionInProgress) { transaction = MongoStaticContext.Context.CreateTransaction(true, new MongoTransactionOptions { Isolation = MongoTransactionIsolation.ReadUncommitted }); } lock (lockObject) { try { cachedRelations = null; var created = MongoStaticContext.Context.EntityRelations.Create(mongoEntityRelation); var relation = Read(mongoEntityRelation.Name); var recRepo = new MongoRecordRepository(); var entityRepo = new MongoEntityRepository(); var originEntity = entityRepo.Read(relation.OriginEntityId); var targetEntity = entityRepo.Read(relation.TargetEntityId); recRepo.CreateRecordField(originEntity.Name, $"#{relation.Name}_targets", null); recRepo.CreateRecordField(targetEntity.Name, $"#{relation.Name}_origins", null); InvalidateRelationIndex(relation); if (transaction != null) { transaction.Commit(); } cachedRelations = null; return(created); } catch { if (transaction != null) { transaction.Rollback(); } throw; } } }
/// <summary> /// Deletes entity relation /// </summary> /// <param name="id"></param> /// <returns></returns> public bool Delete(Guid id) { lock (lockObject) { MongoTransaction transaction = null; if (!MongoStaticContext.Context.TransactionInProgress) { transaction = MongoStaticContext.Context.CreateTransaction(); } try { var relation = Read(id); var recRepo = new MongoRecordRepository(); var entityRepo = new MongoEntityRepository(); var originEntity = entityRepo.Read(relation.OriginEntityId); var targetEntity = entityRepo.Read(relation.TargetEntityId); recRepo.RemoveRecordField(originEntity.Name, $"#{relation.Name}_targets"); recRepo.RemoveRecordField(targetEntity.Name, $"#{relation.Name}_origins"); InvalidateRelationIndex(relation, dropIndexes: true); var result = MongoStaticContext.Context.EntityRelations.Delete(Query.EQ("_id", id)); if (transaction != null) { transaction.Commit(); } cachedRelations = null; return(result); } catch { if (transaction != null) { transaction.Rollback(); } throw; } } }
private void InvalidateRelationIndex(IStorageEntityRelation entityRelation, bool dropIndexes = false) { var entityRepository = new MongoEntityRepository(); var originEntity = entityRepository.Read(entityRelation.OriginEntityId); var targetEntity = entityRepository.Read(entityRelation.TargetEntityId); if (originEntity == null || targetEntity == null) { return; } IStorageField originField = originEntity.Fields.SingleOrDefault(x => x.Id == entityRelation.OriginFieldId); IStorageField targetField = targetEntity.Fields.SingleOrDefault(x => x.Id == entityRelation.TargetFieldId); if (originField == null || targetField == null) { return; } if (entityRelation.RelationType != Api.Models.EntityRelationType.ManyToMany) { var originCollection = MongoStaticContext.Context.GetBsonCollection(MongoRecordRepository.RECORD_COLLECTION_PREFIX + originEntity.Name); if (originCollection == null) { return; } if (originField.Name != "id") { var originIndexes = originCollection.GetIndexes(); var originIndexName = "relation_" + entityRelation.Name + "_" + originField.Name; var originIndex = originIndexes.SingleOrDefault(x => x.Name == originIndexName); if (originIndex != null) { originCollection.DropIndexByName(originIndexName); } if (!dropIndexes) { IndexOptionsBuilder options = IndexOptions.SetUnique(false).SetDropDups(false).SetName(originIndexName).SetBackground(true); originCollection.CreateIndex(new IndexKeysBuilder().Ascending(originField.Name), options); } } var targetCollection = MongoStaticContext.Context.GetBsonCollection(MongoRecordRepository.RECORD_COLLECTION_PREFIX + targetEntity.Name); if (targetEntity == null) { return; } if (targetField.Name != "id") { var targetIndexes = targetCollection.GetIndexes(); var targetIndexName = "relation_" + entityRelation.Name + "_" + targetField.Name; var targetIndex = targetIndexes.SingleOrDefault(x => x.Name == targetIndexName); if (targetIndex != null) { targetCollection.DropIndexByName(targetIndexName); } if (!dropIndexes) { IndexOptionsBuilder options = IndexOptions.SetUnique(false).SetDropDups(false).SetName(targetIndexName).SetBackground(true); targetCollection.CreateIndex(new IndexKeysBuilder().Ascending(targetField.Name), options); } } } else { //at the moment many to many relation do not need any endexes /* * var originCollection = MongoStaticContext.Context.GetBsonCollection(MongoRecordRepository.RECORD_COLLECTION_PREFIX + originEntity.Name); * if (originCollection == null) * return; * * var originIndexes = originCollection.GetIndexes(); * var originIndexName = "relation_" + entityRelation.Name + "_targets"; * var originIndex = originIndexes.SingleOrDefault(x => x.Name == originIndexName); * if (originIndex != null) * originCollection.DropIndexByName(originIndexName); * * if (!dropIndexes) * { * var originFieldName = $"#" + entityRelation.Name + "_targets"; * IndexOptionsBuilder options = IndexOptions.SetUnique(false).SetDropDups(false).SetName(originIndexName).SetBackground(true); * originCollection.CreateIndex(new IndexKeysBuilder().Ascending(originFieldName), options); * } * * var targetCollection = MongoStaticContext.Context.GetBsonCollection(MongoRecordRepository.RECORD_COLLECTION_PREFIX + targetEntity.Name); * if (targetEntity == null) * return; * * var targetIndexes = targetCollection.GetIndexes(); * var targetIndexName = "relation_" + entityRelation.Name + "_origins"; * var targetIndex = targetIndexes.SingleOrDefault(x => x.Name == targetIndexName); * if (targetIndex != null) * targetCollection.DropIndexByName(targetIndexName); * * if (!dropIndexes) * { * var targetFieldName = $"#" + entityRelation.Name + "_origins"; * IndexOptionsBuilder options = IndexOptions.SetUnique(false).SetDropDups(false).SetName(targetIndexName).SetBackground(true); * targetCollection.CreateIndex(new IndexKeysBuilder().Ascending(targetFieldName), options); * } */ } }
/// <summary> /// Deletes many to many relation record /// </summary> /// <param name="relationId"></param> /// <param name="originId"></param> /// <param name="targetId"></param> public void DeleteManyToManyRecord(Guid relationId, Guid originId, Guid targetId) { var entityRepository = new MongoEntityRepository(); var relation = Read(relationId); var originEntity = entityRepository.Read(relation.OriginEntityId); var originField = originEntity.Fields.Single(x => x.Id == relation.OriginFieldId); var targetEntity = entityRepository.Read(relation.TargetEntityId); var targetField = targetEntity.Fields.Single(x => x.Id == relation.TargetFieldId); var originColletion = MongoStaticContext.Context.GetBsonCollection("rec_" + originEntity.Name); var originFieldName = originField.Name; if (originFieldName == "id") { originFieldName = "_id"; } var originRecords = originColletion.Find(Query.EQ(originFieldName, originId)).ToList(); var originRecordsCount = originRecords.Count(); BsonDocument originRecord = null; if (originRecordsCount == 0) { throw new StorageException("There are no record with specified origin id."); } else if (originRecordsCount > 1) { throw new StorageException("There are more than 1 record with same origin id."); } else { originRecord = originRecords[0]; var targetsElementName = $"#{ relation.Name}_targets"; BsonElement bsonElement = null; try { bsonElement = originRecord.GetElement(targetsElementName); } catch { } if (bsonElement != null) { var targets = BsonTypeMapper.MapToDotNetValue(bsonElement.Value) as List <object>; if (targets != null && targets.Contains(targetId)) { targets.Remove(targetId); if (targets.Count == 0) { targets = null; } originRecord[targetsElementName] = BsonTypeMapper.MapToBsonValue(targets); } } else { originRecord[targetsElementName] = BsonTypeMapper.MapToBsonValue(null); } } var targetColletion = MongoStaticContext.Context.GetBsonCollection("rec_" + targetEntity.Name); var targetFieldName = targetField.Name; if (targetFieldName == "id") { targetFieldName = "_id"; } var targetRecords = targetColletion.Find(Query.EQ(targetFieldName, targetId)).ToList(); var targetRecordsCount = targetRecords.Count(); BsonDocument targetRecord = null; if (targetRecordsCount == 0) { throw new StorageException("There are no record with specified target id."); } else if (targetRecordsCount > 1) { throw new StorageException("There are more than 1 record with same target id."); } else { targetRecord = targetRecords[0]; var originsElementName = $"#{ relation.Name}_origins"; BsonElement bsonElement = null; try { bsonElement = targetRecord.GetElement(originsElementName); } catch { } if (bsonElement != null) { var origins = BsonTypeMapper.MapToDotNetValue(bsonElement.Value) as List <object>; if (origins != null && origins.Contains(originId)) { origins.Remove(originId); if (origins.Count == 0) { origins = null; } targetRecord[originsElementName] = BsonTypeMapper.MapToBsonValue(origins); } } else { targetRecord[originsElementName] = BsonTypeMapper.MapToBsonValue(null); } } MongoTransaction transaction = null; if (!MongoStaticContext.Context.TransactionInProgress) { transaction = MongoStaticContext.Context.CreateTransaction(); } try { originColletion.Save(originRecord); targetColletion.Save(targetRecord); if (transaction != null) { transaction.Commit(); } } catch { if (transaction != null) { transaction.Rollback(); } throw; } }
/// <summary> /// Creates entity relation /// </summary> /// <param name="entity"></param> public bool Create(IStorageEntityRelation entityRelation) { if (entityRelation == null) throw new ArgumentNullException("entityRelation"); var mongoEntityRelation = entityRelation as MongoEntityRelation; if (mongoEntityRelation == null) throw new Exception("The specified entityRelation is not mongo storage object."); MongoTransaction transaction = null; if (!MongoStaticContext.Context.TransactionInProgress) transaction = MongoStaticContext.Context.CreateTransaction( true, new MongoTransactionOptions { Isolation= MongoTransactionIsolation.ReadUncommitted}); lock (lockObject) { try { cachedRelations = null; var created = MongoStaticContext.Context.EntityRelations.Create(mongoEntityRelation); var relation = Read(mongoEntityRelation.Name); var recRepo = new MongoRecordRepository(); var entityRepo = new MongoEntityRepository(); var originEntity = entityRepo.Read(relation.OriginEntityId); var targetEntity = entityRepo.Read(relation.TargetEntityId); recRepo.CreateRecordField(originEntity.Name, $"#{relation.Name}_targets", null); recRepo.CreateRecordField(targetEntity.Name, $"#{relation.Name}_origins", null); InvalidateRelationIndex(relation); if (transaction != null) transaction.Commit(); cachedRelations = null; return created; } catch { if (transaction != null) transaction.Rollback(); throw; } } }
private void InvalidateRelationIndex(IStorageEntityRelation entityRelation, bool dropIndexes = false ) { var entityRepository = new MongoEntityRepository(); var originEntity = entityRepository.Read(entityRelation.OriginEntityId); var targetEntity = entityRepository.Read(entityRelation.TargetEntityId); if (originEntity == null || targetEntity == null) return; IStorageField originField = originEntity.Fields.SingleOrDefault(x => x.Id == entityRelation.OriginFieldId); IStorageField targetField = targetEntity.Fields.SingleOrDefault(x => x.Id == entityRelation.TargetFieldId); if (originField == null || targetField == null) return; if (entityRelation.RelationType != Api.Models.EntityRelationType.ManyToMany) { var originCollection = MongoStaticContext.Context.GetBsonCollection(MongoRecordRepository.RECORD_COLLECTION_PREFIX + originEntity.Name); if (originCollection == null) return; if (originField.Name != "id") { var originIndexes = originCollection.GetIndexes(); var originIndexName = "relation_" + entityRelation.Name + "_" + originField.Name; var originIndex = originIndexes.SingleOrDefault(x => x.Name == originIndexName); if (originIndex != null) originCollection.DropIndexByName(originIndexName); if (!dropIndexes) { IndexOptionsBuilder options = IndexOptions.SetUnique(false).SetDropDups(false).SetName(originIndexName).SetBackground(true); originCollection.CreateIndex(new IndexKeysBuilder().Ascending(originField.Name), options); } } var targetCollection = MongoStaticContext.Context.GetBsonCollection(MongoRecordRepository.RECORD_COLLECTION_PREFIX + targetEntity.Name); if (targetEntity == null) return; if (targetField.Name != "id") { var targetIndexes = targetCollection.GetIndexes(); var targetIndexName = "relation_" + entityRelation.Name + "_" + targetField.Name; var targetIndex = targetIndexes.SingleOrDefault(x => x.Name == targetIndexName); if (targetIndex != null) targetCollection.DropIndexByName(targetIndexName); if (!dropIndexes) { IndexOptionsBuilder options = IndexOptions.SetUnique(false).SetDropDups(false).SetName(targetIndexName).SetBackground(true); targetCollection.CreateIndex(new IndexKeysBuilder().Ascending(targetField.Name), options); } } } else { //at the moment many to many relation do not need any endexes /* var originCollection = MongoStaticContext.Context.GetBsonCollection(MongoRecordRepository.RECORD_COLLECTION_PREFIX + originEntity.Name); if (originCollection == null) return; var originIndexes = originCollection.GetIndexes(); var originIndexName = "relation_" + entityRelation.Name + "_targets"; var originIndex = originIndexes.SingleOrDefault(x => x.Name == originIndexName); if (originIndex != null) originCollection.DropIndexByName(originIndexName); if (!dropIndexes) { var originFieldName = $"#" + entityRelation.Name + "_targets"; IndexOptionsBuilder options = IndexOptions.SetUnique(false).SetDropDups(false).SetName(originIndexName).SetBackground(true); originCollection.CreateIndex(new IndexKeysBuilder().Ascending(originFieldName), options); } var targetCollection = MongoStaticContext.Context.GetBsonCollection(MongoRecordRepository.RECORD_COLLECTION_PREFIX + targetEntity.Name); if (targetEntity == null) return; var targetIndexes = targetCollection.GetIndexes(); var targetIndexName = "relation_" + entityRelation.Name + "_origins"; var targetIndex = targetIndexes.SingleOrDefault(x => x.Name == targetIndexName); if (targetIndex != null) targetCollection.DropIndexByName(targetIndexName); if (!dropIndexes) { var targetFieldName = $"#" + entityRelation.Name + "_origins"; IndexOptionsBuilder options = IndexOptions.SetUnique(false).SetDropDups(false).SetName(targetIndexName).SetBackground(true); targetCollection.CreateIndex(new IndexKeysBuilder().Ascending(targetFieldName), options); } */ } }
/// <summary> /// Deletes many to many relation record /// </summary> /// <param name="relationId"></param> /// <param name="originId"></param> /// <param name="targetId"></param> public void DeleteManyToManyRecord(Guid relationId, Guid originId, Guid targetId) { var entityRepository = new MongoEntityRepository(); var relation = Read(relationId); var originEntity = entityRepository.Read(relation.OriginEntityId); var originField = originEntity.Fields.Single(x => x.Id == relation.OriginFieldId); var targetEntity = entityRepository.Read(relation.TargetEntityId); var targetField = targetEntity.Fields.Single(x => x.Id == relation.TargetFieldId); var originColletion = MongoStaticContext.Context.GetBsonCollection("rec_" + originEntity.Name); var originFieldName = originField.Name; if (originFieldName == "id") originFieldName = "_id"; var originRecords = originColletion.Find(Query.EQ(originFieldName, originId)).ToList(); var originRecordsCount = originRecords.Count(); BsonDocument originRecord = null; if (originRecordsCount == 0) throw new StorageException("There are no record with specified origin id."); else if (originRecordsCount > 1) throw new StorageException("There are more than 1 record with same origin id."); else { originRecord = originRecords[0]; var targetsElementName = $"#{ relation.Name}_targets"; BsonElement bsonElement = null; if (originRecord.Elements.Any(x => x.Name == targetsElementName)) bsonElement = originRecord.GetElement(targetsElementName); //try { bsonElement = originRecord.GetElement(targetsElementName); } catch { } if (bsonElement != null) { var targets = BsonTypeMapper.MapToDotNetValue(bsonElement.Value) as List<object>; if (targets != null && targets.Contains(targetId)) { targets.Remove(targetId); if (targets.Count == 0) targets = null; originRecord[targetsElementName] = BsonTypeMapper.MapToBsonValue(targets); } } else originRecord[targetsElementName] = BsonTypeMapper.MapToBsonValue(null); } var targetColletion = MongoStaticContext.Context.GetBsonCollection("rec_" + targetEntity.Name); var targetFieldName = targetField.Name; if (targetFieldName == "id") targetFieldName = "_id"; var targetRecords = targetColletion.Find(Query.EQ(targetFieldName, targetId)).ToList(); var targetRecordsCount = targetRecords.Count(); BsonDocument targetRecord = null; if (targetRecordsCount == 0) throw new StorageException("There are no record with specified target id."); else if (targetRecordsCount > 1) throw new StorageException("There are more than 1 record with same target id."); else { targetRecord = targetRecords[0]; var originsElementName = $"#{ relation.Name}_origins"; BsonElement bsonElement = null; if (targetRecord.Elements.Any(x => x.Name == originsElementName)) bsonElement = targetRecord.GetElement(originsElementName); //try { bsonElement = targetRecord.GetElement(originsElementName); } catch { } if (bsonElement != null) { var origins = BsonTypeMapper.MapToDotNetValue(bsonElement.Value) as List<object>; if (origins != null && origins.Contains(originId)) { origins.Remove(originId); if (origins.Count == 0) origins = null; targetRecord[originsElementName] = BsonTypeMapper.MapToBsonValue(origins); } } else targetRecord[originsElementName] = BsonTypeMapper.MapToBsonValue(null); } MongoTransaction transaction = null; if (!MongoStaticContext.Context.TransactionInProgress) transaction = MongoStaticContext.Context.CreateTransaction(); try { originColletion.Save(originRecord); targetColletion.Save(targetRecord); if (transaction != null) transaction.Commit(); } catch { if (transaction != null) transaction.Rollback(); throw; } }
/// <summary> /// Deletes entity relation /// </summary> /// <param name="id"></param> /// <returns></returns> public bool Delete(Guid id) { lock (lockObject) { MongoTransaction transaction = null; if(!MongoStaticContext.Context.TransactionInProgress) transaction = MongoStaticContext.Context.CreateTransaction(); try { var relation = Read(id); var recRepo = new MongoRecordRepository(); var entityRepo = new MongoEntityRepository(); var originEntity = entityRepo.Read(relation.OriginEntityId); var targetEntity = entityRepo.Read(relation.TargetEntityId); recRepo.RemoveRecordField(originEntity.Name, $"#{relation.Name}_targets"); recRepo.RemoveRecordField(targetEntity.Name, $"#{relation.Name}_origins"); InvalidateRelationIndex(relation, dropIndexes: true); var result = MongoStaticContext.Context.EntityRelations.Delete(Query.EQ("_id", id)); if (transaction != null) transaction.Commit(); cachedRelations = null; return result; } catch { if (transaction != null) transaction.Rollback(); throw; } } }