public IEnumerable <RelationById> PerformGetParentRelations(HiveId childId, RelationType relationType = null) { if (childId.Value.Type != HiveIdValueTypes.Guid) { return(Enumerable.Empty <RelationById>()); } using (NhProfilerLogging.Start(NhSession, "PerformGetParentRelations", new OdbcParameter("childId", childId), new OdbcParameter("relationType", relationType))) { var value = (Guid)childId.Value; // Reference the value here because otherwise it gets lost in NH's query cache var query = NhSession.QueryOver <NodeRelation>() .Where(x => x.EndNode.Id == value) .Fetch(x => x.StartNode).Lazy .Fetch(x => x.EndNode).Lazy .Fetch(x => x.NodeRelationTags).Eager .Fetch(x => x.NodeRelationType).Eager; if (relationType != null) { var relationName = relationType.RelationName; var nodeRelations = query.JoinQueryOver <NodeRelationType>(x => x.NodeRelationType).Where(x => x.Alias == relationName).Cacheable().List(); return(nodeRelations.Select(MapNodeRelation).ToList()); } var relations = query.Cacheable().List(); return(relations.Select(MapNodeRelation).ToList()); } }
protected override void PerformAddOrUpdate(TypedEntity entity) { Mandate.ParameterNotNull(entity, "persistedEntity"); using (NhProfilerLogging.Start(Helper.NhSession, "PerformAddOrUpdate", new OdbcParameter("entity", entity))) { // Note that it should be the caller's responsibility to add to revisions but the Cms backoffice code needs to change // to do that, so this is included to avoid breaking assumptions about auto-created versions until then if (Revisions.CanWrite) { var newRevision = new Revision <TypedEntity>(entity); Revisions.AddOrUpdate(newRevision); return; } else { if (TryUpdateExisting(entity)) { return; } Helper.MapAndMerge(entity, FrameworkContext.TypeMappers); } } }
public IEnumerable <NodeVersion> GetNodeVersionsByStatusDesc(Guid[] nodeIds = null, RevisionStatusType revisionStatus = null, bool limitToLatestRevision = true) { using (NhProfilerLogging.Start(NhSession, "GetNodeVersionsByStatusDesc", new OdbcParameter("nodeIds", nodeIds != null ? string.Join(", ", nodeIds.Select(x => x.ToString())) : "(empty)"), new OdbcParameter("revisionStatus", revisionStatus != null ? revisionStatus.Alias : "(empty)"), new OdbcParameter("limitToLatestRevision", limitToLatestRevision))) { //NhSession.Clear(); var query = GenerateVersionedQueryPlusAttributes(nodeIds, revisionStatus, limitToLatestRevision); var nodeVersions = query.List(); return(nodeVersions.Distinct()); //// The query creates a Cartesian product because of the joins, but it's still more efficient than using Futures until it's possible for NH //// to recognise AttributeStringValues (for example) when selecting only the 8 that match the Attribute; at the moment you have to left-join //// Attribute to AttributeStringValues which causes Attribute*AttributeStringValues rows anyway //var foundVersions = attribs.List().Select(x => x.NodeVersion).Distinct(); //// Because we selected from Attributes in order to do an efficient query for NodeVersions that have Attributes, we'll actually //// miss any NodeVersions that have zero attributes, such as the SystemRoot node. Therefore, for any items that were requested //// but not returned by the first query, we'll request just the NodeVersion //var idsFound = foundVersions.Select(x => x.Node.Id).Distinct().ToArray(); //// We need to account for if this method was called without nodeIds specified though, in which case we'll need to //// get all of the nodeIds that have an attached version from the database //Guid[] idsNotFound; //if (nodeIds != null) //{ // idsNotFound = nodeIds.Except(idsFound).ToArray(); //} //else //{ // var getAllIds = NhSession.QueryOver<NodeVersion>().Select(x => x.Node.Id).List<Guid>().Distinct(); // idsNotFound = getAllIds.Except(idsFound).ToArray(); //} //if (idsNotFound.Any()) //{ // NodeVersionStatusHistory outerHistoryForSort = null; // var outerQuery = NhSession.QueryOver<NodeVersion>(() => outerVersionSelect) // .Fetch(x => x.Attributes).Eager // Even though we know these nodes have no Attributes, we need to allow NH to know this without // .Fetch(x => x.Node).Eager // issuing a separate request during mapping of the Attributes / Node properties // .JoinQueryOver(x => outerVersionSelect.NodeVersionStatuses, () => outerHistoryForSort) // .OrderBy(() => outerHistoryForSort.Date).Asc // .WithSubquery.WhereProperty(() => outerVersionSelect.Id).In(subSelectTopStatusByDateWithFilter) // .And(() => outerVersionSelect.Node.Id.IsIn(idsNotFound)); // foundVersions = foundVersions.Concat(outerQuery.List()); //} } }
public void MapAndMerge(AbstractEntity entity, MappingEngineCollection mappers) { using (DisposableTimer.TraceDuration <NhSessionHelper>("Start MapAndMerge for entity " + entity.Id, "End MapAndMerge")) using (NhProfilerLogging.Start(NhSession, "MapAndMerge", new OdbcParameter("entity", entity))) { var rdbmsEntity = mappers.MapToIntent <IReferenceByGuid>(entity); // Track ID generation on the Rdbms object so that it can be pinged to the AbstractEntity upon Save/Update commit rdbmsEntity = NhSession.Merge(rdbmsEntity) as IReferenceByGuid; //InnerDataContext.NhibernateSession.SaveOrUpdate(rdbmsEntity); mappers.Map(rdbmsEntity, entity, rdbmsEntity.GetType(), entity.GetType()); } }
public IEnumerable <RelationById> PerformGetBranchRelations(HiveId siblingId, RelationType relationType = null) { if (siblingId.Value.Type != HiveIdValueTypes.Guid) { return(Enumerable.Empty <RelationById>()); } using (NhProfilerLogging.Start(NhSession, "PerformGetBranchRelations", new OdbcParameter("siblingId", siblingId), new OdbcParameter("relationType", relationType))) { var value = (Guid)siblingId.Value; // Reference the value here because otherwise it gets lost in NH's query cache var query = NhSession.QueryOver <NodeRelation>() .Fetch(x => x.StartNode).Lazy .Fetch(x => x.EndNode).Lazy .Fetch(x => x.NodeRelationTags).Eager .Fetch(x => x.NodeRelationType).Eager; var parentQuery = QueryOver.Of <NodeRelation>().Where(x => x.EndNode.Id == value); if (relationType != null) { var copyRelationName = relationType.RelationName; var parentQueryWithType = parentQuery .JoinQueryOver(x => x.NodeRelationType) .Where(x => x.Alias == copyRelationName); return(query.WithSubquery.WhereProperty(x => x.StartNode.Id).In(parentQueryWithType.Select(x => x.StartNode.Id).Take(1)) .CacheRegion("Relations").Cacheable().List().Select(MapNodeRelation)); } else { return(query.WithSubquery.WhereProperty(x => x.StartNode.Id).In(parentQuery.Select(x => x.StartNode.Id).Take(1)) .CacheRegion("Relations").Cacheable().List().Select(MapNodeRelation)); } } }
public RelationById PerformFindRelation(HiveId sourceId, HiveId destinationId, RelationType relationType) { if (sourceId.Value.Type != HiveIdValueTypes.Guid || destinationId.Value.Type != HiveIdValueTypes.Guid) { return(null); } using (NhProfilerLogging.Start(NhSession, "PerformFindRelation", new OdbcParameter("sourceId", sourceId), new OdbcParameter("destinationId", destinationId), new OdbcParameter("relationType", relationType))) { // Reference the values here because otherwise it gets lost in NH's query cache var sourceValue = (Guid)sourceId.Value; var destValue = (Guid)destinationId.Value; var relationName = relationType.RelationName; var firstRelation = GetDbRelation(relationName, sourceValue, destValue).FirstOrDefault(); return(firstRelation != null?MapNodeRelation(firstRelation) : null); } }
public void MapAndMerge <T>(Revision <T> entity, MappingEngineCollection mappers) where T : class, IVersionableEntity { HiveId hiveId = entity.MetaData != null ? entity.MetaData.Id : HiveId.Empty; HiveId entityId = entity.Item != null ? entity.Item.Id : HiveId.Empty; using (DisposableTimer.TraceDuration <NhSessionHelper>("Start MapAndMerge for revision " + hiveId + " entity " + entityId, "End MapAndMerge")) using (NhProfilerLogging.Start(NhSession, "MapAndMerge<T> (Revision<T>)", new OdbcParameter("entity", entity))) { var rdbmsEntity = mappers.MapToIntent <IReferenceByGuid>(entity); // Track ID generation on the Rdbms object so that it can be pinged to the AbstractEntity upon Save/Update commit rdbmsEntity = NhSession.Merge(rdbmsEntity) as IReferenceByGuid; // 16th Jan 12 (APN) NH is not flushing if the above merged entity is queried before the transaction is committed, despite // the flushmode being Auto. So, explicit call to Flush here pending a bugfix/ better solution NhSession.Flush(); //InnerDataContext.NhibernateSession.SaveOrUpdate(rdbmsEntity); mappers.Map(rdbmsEntity, entity, rdbmsEntity.GetType(), entity.GetType()); } }