/// <summary> /// Set a value into secured data. /// </summary> /// <param name="tenantId">The tenant Id</param> /// <param name="context">A string representing the context of the storage.</param> /// <param name="secureId">The secured Id as proved by the Set call.</param> /// <param name="value">The value to be stored</param> public void Update(Guid secureId, string value) { if (secureId == Guid.Empty) { throw new ArgumentException(nameof(secureId)); } if (value == null) { throw new ArgumentNullException(nameof(value)); } long userId; RequestContext.TryGetUserId(out userId); using (DatabaseContextInfo.SetContextInfo("Update secure data")) using (DatabaseContext ctx = DatabaseContext.GetContext( )) { using (IDbCommand command = ctx.CreateCommand("spSecuredDataUpdate", CommandType.StoredProcedure)) { ctx.AddParameter(command, "@secureId", DbType.Guid, secureId); ctx.AddParameter(command, "@data", DbType.String, value); ctx.AddParameter(command, "@context", DbType.AnsiString, DatabaseContextInfo.GetMessageChain(userId)); var rows = command.ExecuteNonQuery( ); if (rows < 1) { throw new SecureIdNotFoundException($"Key not present. secureId: '{secureId}'"); } } } }
/// <summary> /// Executes the filter action asynchronously. /// </summary> /// <param name="actionContext">The action context.</param> /// <param name="cancellationToken">The cancellation token assigned for this task.</param> /// <param name="continuation">The delegate function to continue after the action method is invoked.</param> /// <returns> /// The newly created task for this operation. /// </returns> public Task <HttpResponseMessage> ExecuteActionFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func <Task <HttpResponseMessage> > continuation) { // Get web context string entryPoint = "Failed"; try { entryPoint = actionContext.ControllerContext.Controller.GetType( ).Name + "." + actionContext.ActionDescriptor.ActionName; } catch { } using (DatabaseContextInfo.SetContextInfo($"WebApi - {actionContext.ControllerContext.ControllerDescriptor.ControllerName}.{actionContext.ActionDescriptor.ActionName}")) using (EntryPointContext.SetEntryPoint(entryPoint)) { ProcessMonitorWriter.Instance.Write(entryPoint); RequestContext requestContext = RequestContext.GetContext( ); if (requestContext != null && requestContext.IsValid) { // Attach timezone string tz = HttpContext.Current.Request.Headers.Get("Tz"); if (!string.IsNullOrEmpty(tz)) { // Set the timezone in the logical context var contextData = new RequestContextData(requestContext.Identity, requestContext.Tenant, requestContext.Culture, tz); RequestContext.SetContext(contextData); } } // Do the actual API call work return(continuation( )); } }
public void TestMessageWithSingleValueThatFallsBelowTheMaximumLength( ) { using (DatabaseContextInfo.SetContextInfo(TestString1)) { string message = DatabaseContextInfo.GetMessageChain(0); Assert.AreEqual($"u:0,{TestString1}", message); } }
public void TestMessageWithSingleValueThatExceedTheMaximumLength( ) { using (DatabaseContextInfo.SetContextInfo(TestString1.PadRight(MaxLength - 3, '!'))) { string message = DatabaseContextInfo.GetMessageChain(0); Assert.AreEqual("u:0,The quick brown fox jumps over the lazy dog!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!...", message); } }
public void TestMessageWithSingleValueThatEqualsTheMaximumLength( ) { using (DatabaseContextInfo.SetContextInfo(TestString1.PadRight(MaxLength - 4, '!'))) { string message = DatabaseContextInfo.GetMessageChain(0); Assert.AreEqual($"u:0,{TestString1.PadRight( MaxLength - 4, '!' )}", message); } }
/// <summary> /// Updates the user accounts last logon time. /// </summary> /// <param name="entityId">The entity identifier.</param> /// <remarks> /// This intentionally bypasses the entity model and directly updates the database asynchronously. /// Any cached values are removed from the read-only cache upon completion. /// Cache invalidators are not invoked due to this call. /// </remarks> private static void UpdateUserAccountLastLogon(long entityId) { long tenantId = RequestContext.TenantId; long fieldId = WellKnownAliases.CurrentTenant.LastLogon; DateTime now = DateTime.UtcNow; ThreadPool.QueueUserWorkItem(state => { using (DatabaseContextInfo.SetContextInfo($"Update last logon for user '{entityId}'")) using (DatabaseContext ctx = DatabaseContext.GetContext( )) { using (var command = ctx.CreateCommand("spData_DateTimeMerge", CommandType.StoredProcedure)) { ctx.AddParameter(command, "@entityId", DbType.Int64, entityId); ctx.AddParameter(command, "@tenantId", DbType.Int64, tenantId); ctx.AddParameter(command, "@fieldId", DbType.Int64, fieldId); ctx.AddParameter(command, "@data", DbType.DateTime, now); ctx.AddParameter(command, "@context", DbType.AnsiString, DatabaseContextInfo.GetMessageChain(entityId)); command.ExecuteNonQuery( ); IEntityFieldValues values; ///// // Remove the last logon time from the field cache (if it exists). ///// if (EntityFieldCache.Instance.TryGetValue(entityId, out values)) { object lastLogon; if (values.TryGetValue(fieldId, out lastLogon)) { values [fieldId] = now; } } ///// // Invalidate any items referencing the LastLogon item (NOT the UserAccount item) //// var cacheInvalidators = new CacheInvalidatorFactory( ).CacheInvalidators.ToList( ); List <IEntity> fieldTypes = new List <IEntity> { new IdEntity(fieldId) }; foreach (ICacheInvalidator cacheInvalidator in cacheInvalidators) { cacheInvalidator.OnEntityChange(fieldTypes, InvalidationCause.Save, null); } } } }); }
public void TestMessageContainsTwoValuesWithTheLastValueTruncated( ) { using (DatabaseContextInfo.SetContextInfo("Hi")) { using (DatabaseContextInfo.SetContextInfo("HelloThereWorld")) { string message = DatabaseContextInfo.GetMessageChain(0, "->", 20); Assert.AreEqual("u:0,Hi->HelloTher...", message); } } }
public void TestEmpty( ) { using (DatabaseContextInfo.SetContextInfo(string.Empty)) { ///// // Use CallerMemberName ///// string message = DatabaseContextInfo.GetMessageChain(0); Assert.AreEqual("u:0,TestEmpty", message); } }
public void TestMessageWithMultipleValuesThatExceedTheMaximumLength( ) { using (DatabaseContextInfo.SetContextInfo(TestString1.PadRight(MaxLength / 2 + 1, '!'))) { using (DatabaseContextInfo.SetContextInfo(TestString2.PadRight(MaxLength / 2 + 1, '@'))) { string message = DatabaseContextInfo.GetMessageChain(0); Assert.AreEqual("u:0,The quick brown fox jumps over the lazy dog!!!!!!!!!!!!!!...->The rain in spain stays mainly on the plain@@@@@@@@@@@@@@...", message); } } }
/// <summary> /// Called when an entity field is saved. /// </summary> /// <param name="entity">The entity.</param> void IEntityFieldSave.OnSave(IEntity entity) { if (entity == null) { return; } long userId; RequestContext.TryGetUserId(out userId); ///// // This is already running in a transaction ///// using (DatabaseContext ctx = DatabaseContext.GetContext( )) { ///// // Command takes an Update Lock under SERIALIZABLE isolation to ensure concurrency. ///// using (DatabaseContextInfo.SetContextInfo("Update autonumber instance")) using (IDbCommand command = ctx.CreateCommand("spUpdateAutoNumberInstance", CommandType.StoredProcedure)) { ctx.AddParameter(command, "@entityId", DbType.Int64, entity.Id); ctx.AddParameter(command, "@fieldId", DbType.Int64, _field.Id); ctx.AddParameter(command, "@tenantId", DbType.Int64, RequestContext.TenantId); ctx.AddParameter(command, "@context", DbType.AnsiString, DatabaseContextInfo.GetMessageChain(userId)); object newId = command.ExecuteScalar( ); if (newId != null && newId != DBNull.Value) { IEntityFieldValues readonlyFields; ///// // Update the read-only cache with the new value. ///// if (!EntityFieldCache.Instance.TryGetValue(entity.Id, out readonlyFields)) { readonlyFields = new EntityFieldValues( ); EntityFieldCache.Instance[entity.Id] = readonlyFields; } ///// // Set the value. ///// readonlyFields[_field.Id] = ( int )newId; } } } }
/// <summary> /// Creates or removes a permission relationship between a tenant and an app in the global tenant. /// </summary> private static void UpdateTenantPermissionRelationship(long tenantId, long appId, string relationshipAlias, bool grant) { const string grantSql = @"-- Grant app access IF ( @context IS NOT NULL ) BEGIN DECLARE @contextInfo VARBINARY(128) = CONVERT( VARBINARY(128), @context ) SET CONTEXT_INFO @contextInfo END declare @relId bigint = dbo.fnAliasNsId( @relAlias, 'core', default ) if not exists ( select 1 from Relationship where TenantId = 0 and TypeId = @relId and FromId = @tenantId and ToId = @appId ) begin insert into Relationship (TenantId, TypeId, FromId, ToId) values (0, @relId, @tenantId, @appId) end "; const string denySql = @"-- Deny app access IF ( @context IS NOT NULL ) BEGIN DECLARE @contextInfo VARBINARY(128) = CONVERT( VARBINARY(128), @context ) SET CONTEXT_INFO @contextInfo END declare @relId bigint = dbo.fnAliasNsId( @relAlias, 'core', default ) delete from Relationship where TenantId = 0 and TypeId = @relId and FromId = @tenantId and ToId = @appId "; long userId; RequestContext.TryGetUserId(out userId); using (DatabaseContextInfo.SetContextInfo("Update tenant permission relationship")) using (DatabaseContext ctx = DatabaseContext.GetContext( )) { string sql = grant ? grantSql : denySql; using (IDbCommand command = ctx.CreateCommand(sql)) { ctx.AddParameter(command, "@relAlias", DbType.String, relationshipAlias); ctx.AddParameter(command, "@tenantId", DbType.Int64, tenantId); ctx.AddParameter(command, "@appId", DbType.Int64, appId); ctx.AddParameter(command, "@context", DbType.AnsiString, DatabaseContextInfo.GetMessageChain(userId)); command.ExecuteNonQuery( ); } } }
public void TestMessageContainsMultipleValuesWithTheCenterValueDroppedAndTheLastValueTruncated( ) { using (DatabaseContextInfo.SetContextInfo("Hi")) { using (DatabaseContextInfo.SetContextInfo("There")) { using (DatabaseContextInfo.SetContextInfo("HelloWorld")) { string message = DatabaseContextInfo.GetMessageChain(0, "->", 20); Assert.AreEqual("u:0,Hi->...->Hell...", message); } } } }
/// <summary> /// Deletes the tenant from the entity model. /// </summary> /// <param name="tenantId">The tenant id.</param> public static void DeleteTenant(long tenantId) { EventLog.Application.WriteWarning("Deleting tenant " + tenantId); long userId; RequestContext.TryGetUserId(out userId); using (DatabaseContext ctx = DatabaseContext.GetContext( )) { // Delete the tenant entity instance itself. // Note: this is stored in the root tenant using (new AdministratorContext( )) { Entity.Delete(tenantId); } // Delete the data using (DatabaseContextInfo.SetContextInfo($"Delete tenant {tenantId}")) using (IDbCommand command = ctx.CreateCommand("spDeleteTenant", CommandType.StoredProcedure)) { ctx.AddParameter(command, "@tenantId", DbType.Int64, tenantId); command.AddParameter("@context", DbType.AnsiString, DatabaseContextInfo.GetMessageChain(userId)); command.ExecuteNonQuery( ); } } ///// // Remove the cached tenant id. ///// List <string> matchingTenants = TenantIdCache.Where(pair => pair.Value == tenantId).Select(pair => pair.Key).ToList( ); foreach (string matchingTenant in matchingTenants) { TenantIdCache.Remove(matchingTenant); } TenantNameCache.Remove(tenantId); EventLog.Application.WriteWarning("Deleted tenant " + tenantId); }
/// <summary> /// Upgrades this instance. /// </summary> /// <param name="solutions">The solutions.</param> public static void Upgrade(IEnumerable <Solution> solutions) { long autoNumberValueId = WellKnownAliases.CurrentTenant.AutoNumberValue; long userId; RequestContext.TryGetUserId(out userId); ///// // If the 'core:autoNumberValue' alias exists, convert all auto number instances // that are of the old type, regardless of solution that they belong to. ///// using (DatabaseContext context = DatabaseContext.GetContext(true)) { using (DatabaseContextInfo.SetContextInfo("Upgrade autonumber instances")) using (var command = context.CreateCommand("spUpgradeAutoNumberInstance", CommandType.StoredProcedure)) { context.AddParameter(command, "@tenantId", DbType.Int64, RequestContext.TenantId); context.AddParameter(command, "@context", DbType.AnsiString, DatabaseContextInfo.GetMessageChain(userId)); command.ExecuteNonQuery( ); } using (DatabaseContextInfo.SetContextInfo("Upgrade autonumber start values")) using (var command = context.CreateCommand("spUpgradeAutoNumberStartingNumber", CommandType.StoredProcedure)) { context.AddParameter(command, "@tenantId", DbType.Int64, RequestContext.TenantId); context.AddParameter(command, "@context", DbType.AnsiString, DatabaseContextInfo.GetMessageChain(userId)); var solutionIdParameter = context.AddParameter(command, "@solutionId", DbType.Int64); foreach (Solution solution in solutions) { solutionIdParameter.Value = solution.Id; command.ExecuteNonQuery( ); } } context.CommitTransaction( ); } }
public void TestMessageContainsMultipleValuesWithNoValuesDropped( ) { using (DatabaseContextInfo.SetContextInfo("One")) { using (DatabaseContextInfo.SetContextInfo("Two")) { using (DatabaseContextInfo.SetContextInfo("Three")) { using (DatabaseContextInfo.SetContextInfo("Four")) { using (DatabaseContextInfo.SetContextInfo("Five")) { string message = DatabaseContextInfo.GetMessageChain(0); Assert.AreEqual("u:0,One->Two->Three->Four->Five", message); } } } } } }
/// <summary> /// Creates the tenant. /// </summary> /// <param name="name">The name.</param> /// <param name="description">The description.</param> /// <returns></returns> public static long CreateTenant(string name, string description = null) { using (new GlobalAdministratorContext( )) using (DatabaseContextInfo.SetContextInfo($"Create tenant '{name}'")) { ///// // Create the specified tenant ///// var tenant = Entity.Create <Tenant>( ); tenant.Name = name; tenant.Description = description ?? name + " tenant"; if (name == "EDC") { tenant.Alias = "core:edcTenant"; } tenant.Save( ); return(tenant.Id); } }
public void TestMessageContainsMultipleValuesWithMultipleCenterValuesDropped( ) { using (DatabaseContextInfo.SetContextInfo("aa")) { using (DatabaseContextInfo.SetContextInfo("bb")) { using (DatabaseContextInfo.SetContextInfo("cc")) { using (DatabaseContextInfo.SetContextInfo("dd")) { using (DatabaseContextInfo.SetContextInfo("ee")) { using (DatabaseContextInfo.SetContextInfo("ff")) { string message = DatabaseContextInfo.GetMessageChain(0, "->", 20); Assert.AreEqual("u:0,aa->bb->...->ff", message); } } } } } } }
/// <summary> /// Writes the specified audit log entry. /// </summary> /// <param name="entryData">The entry data.</param> /// <exception cref="System.ArgumentNullException">entryData</exception> public void Write(IAuditLogEntryData entryData) { if (entryData == null) { throw new ArgumentNullException(nameof(entryData)); } using (DatabaseContextInfo.SetContextInfo("Write Audit Log")) using (new SecurityBypassContext()) { if (!CanWrite(entryData)) { return; } IEntity logEntry = Entity.Create(entryData.AuditLogEntryType); // Set type specific fields foreach (var kvp in entryData.Parameters) { logEntry.SetField(kvp.Key, kvp.Value); } // Set base type fields and relationships logEntry.SetField("name", entryData.AuditLogEntryType.Name); logEntry.SetField("auditLogEntrySuccess", entryData.Success); logEntry.SetField("auditLogEntryUser", entryData.UserName); logEntry.SetField("auditLogEntryCreatedDate", entryData.CreatedDate); logEntry.SetRelationships("auditLogEntrySeverity", new EntityRelationship <AuditLogSeverityEnum>(entryData.Severity).ToEntityRelationshipCollection(), Direction.Forward); logEntry.SetField("auditLogEntryMessage", entryData.Message); logEntry.Save(); _auditLogDeleter.Purge(); } }
/// <summary> /// Imports the tenant. /// </summary> /// <param name="packagePath">The package path.</param> /// <param name="tenantName">Name of the tenant.</param> /// <param name="overwrite"> /// if set to <c>true</c> [overwrite]. /// </param> /// <param name="context">The context.</param> /// <exception cref="System.ArgumentNullException">tenantStorePath</exception> /// <exception cref="System.InvalidOperationException"> /// The package does not contain a tenant. /// or /// </exception> /// <exception cref="System.ArgumentException">The package is corrupt.</exception> /// <remarks> /// If a tenant with the same name already exists, an exception will be thrown. /// To overwrite an existing tenant with the same name, call OverwriteTenant. /// </remarks> /// <returns>the tenant id</returns> private static long ImportTenant_Impl(string packagePath, string tenantName, bool overwrite, IProcessingContext context) { if (string.IsNullOrEmpty(packagePath)) { throw new ArgumentNullException("packagePath"); } if (context == null) { context = new ProcessingContext( ); } context.Report.StartTime = DateTime.Now; try { ///// // Create source to load app data from tenant ///// using (var source = FileManager.CreateDataSource(packagePath)) { Metadata metadata = source.GetMetadata(context); if (metadata.Type == SourceType.AppPackage) { throw new InvalidOperationException("The package does not contain a tenant."); } if (string.IsNullOrEmpty(tenantName)) { tenantName = metadata.Name; } if (string.IsNullOrEmpty(tenantName)) { throw new ArgumentException("The package is corrupt."); } bool deleteExistingTenant = false; if (TenantExists(tenantName)) { if (overwrite) { deleteExistingTenant = true; } else { throw new InvalidOperationException(string.Format("The tenant '{0}' already exists.", tenantName)); } } long userId; RequestContext.TryGetUserId(out userId); ///// // Create target to write to SQLite database ///// using (var target = new TenantCopyTarget( )) { Tenant tenant; ///// // Create the tenant. ///// using (new GlobalAdministratorContext( )) { if (deleteExistingTenant) { Tenant existingTenant = Entity.GetByName <Tenant>(tenantName).FirstOrDefault( ); if (existingTenant != null) { using (DatabaseContextInfo.SetContextInfo("Delete existing tenant")) using (IDbCommand command = target.CreateCommand( )) { command.CommandText = "spDeleteTenant"; command.CommandType = CommandType.StoredProcedure; command.Parameters.Add(new SqlParameter("@tenantId", existingTenant.Id)); command.AddParameter("@context", DbType.AnsiString, DatabaseContextInfo.GetMessageChain(userId)); command.ExecuteNonQuery( ); } } } tenant = Entity.Create <Tenant>( ); tenant.Name = tenantName; tenant.Description = tenantName + " tenant"; tenant.Save( ); target.TenantId = tenant.Id; } ///// // Copy the data ///// var processor = new CopyProcessor(source, target, context); processor.MigrateData( ); ///// // Commit the changes. ///// target.Commit( ); return(tenant.Id); } } } finally { ForeignKeyHelper.Trust( ); context.Report.EndTime = DateTime.Now; } }
/// <summary> /// Saves the specified CTX. /// </summary> /// <param name="context">The database context.</param> /// <returns> /// A mapping of the old entity IDs to new entity IDs. If no cloning occurred, /// this returns an empty dictionary. /// </returns> public IDictionary <long, long> Save(DatabaseContext context) { if (context == null) { throw new ArgumentNullException("context"); } IDictionary <long, long> clonedIds = new Dictionary <long, long>( ); using (DatabaseContextInfo dbContextInfo = DatabaseContextInfo.SetContextInfo("Save")) using (IDbCommand command = context.CreateCommand( )) { command.CommandText = "dbo.spSaveGraphSave"; command.CommandType = CommandType.StoredProcedure; command.AddParameter("@tenantId", DbType.Int64, RequestContext.TenantId); PopulateInputEntitiesTable(); long userId; RequestContext.TryGetUserId(out userId); command.AddParameter("@context", DbType.AnsiString, DatabaseContextInfo.GetMessageChain(userId)); var transactionId = command.AddParameter("@transactionId", DbType.Int64); transactionId.Direction = ParameterDirection.Output; bool haveInputEntities = AddInputEntitiesParameter(command); bool haveClones = AddEntityClonesParameters(command); bool haveDeletions = AddDeletionParameters(command); bool haveAdditions = AddAdditionParameters(command); bool haveMiscStatements = AddMiscSqlStatementParameter(command); bool haveChanges = haveInputEntities || haveClones || haveDeletions || haveAdditions || haveMiscStatements; if (!haveChanges) { return(clonedIds); } using (IDataReader reader = command.ExecuteReader( )) { ///// // Read mapping between temporary ids and persisted ids. ///// while (reader.Read()) { long oldId = reader.GetInt64(0); long newId = reader.GetInt64(1); Mapping[oldId] = newId; } ///// // If there were any clone operations, a separate result set containing the source // and destination ids will be returned ///// if (reader.NextResult()) { while (reader.Read()) { clonedIds[reader.GetInt64(0)] = reader.GetInt64(1); } } ///// // Check for exceptions that occur AFTER the last expected result set is returned. ///// if (reader.NextResult( )) { ///// // Exceptions thrown from Sql Server will appear as a separate result set when // accessed using ExecuteReader. This means all results sets that occur before // the failure condition will still be successfully returned. Must check for // exceptions that occur AFTER the last EXPECTED result set has been returned. ///// } } if (transactionId.Value != null && transactionId.Value != DBNull.Value) { dbContextInfo.TransactionId = ( long )transactionId.Value; } } return(clonedIds); }
/// <summary> /// Fixes the navigation section parent folder. /// </summary> /// <param name="child">The child.</param> /// <param name="parent">The parent.</param> private static void FixNavSectionParentFolder(Guid child, Guid parent) { try { const string commandText = @"-- Fix NavSection Parent Folder DECLARE @resourceInFolder BIGINT = dbo.fnAliasNsId( 'resourceInFolder', 'console', @tenantId ) DECLARE @childId BIGINT DECLARE @parentId BIGINT DECLARE @currentParentId BIGINT IF ( @context IS NOT NULL ) BEGIN DECLARE @contextInfo VARBINARY(128) = CONVERT( VARBINARY(128), @context ) SET CONTEXT_INFO @contextInfo END SELECT @childId = Id FROM Entity WHERE TenantId = @tenantId AND UpgradeId = @child IF ( @childId IS NULL ) BEGIN RETURN END SELECT @parentId = Id FROM Entity WHERE TenantId = @tenantId AND UpgradeId = @parent IF ( @parentId IS NULL ) BEGIN RETURN END MERGE Relationship AS t USING ( SELECT @tenantId, @resourceInFolder, @childId ) AS s ( TenantId, TypeId, FromId ) ON ( s.TenantId = t.TenantId AND s.TypeId = t.TypeId AND s.FromId = t.FromId ) WHEN MATCHED AND ( t.ToId <> @parentId ) THEN UPDATE SET ToId = @parentId WHEN NOT MATCHED THEN INSERT (TenantId, TypeId, FromId, ToId ) VALUES ( @tenantId, @resourceInFolder, @childId, @parentId );" ; long userId; RequestContext.TryGetUserId(out userId); using (DatabaseContextInfo.SetContextInfo("Fix nav section parent folder")) using (DatabaseContext ctx = DatabaseContext.GetContext( )) { using (var command = ctx.CreateCommand(commandText)) { ctx.AddParameter(command, "@tenantId", System.Data.DbType.Int64, RequestContext.TenantId); ctx.AddParameter(command, "@child", System.Data.DbType.Guid, child); ctx.AddParameter(command, "@parent", System.Data.DbType.Guid, parent); ctx.AddParameter(command, "@context", System.Data.DbType.AnsiString, DatabaseContextInfo.GetMessageChain(userId)); command.ExecuteNonQuery( ); } } } catch (Exception exc) { EventLog.Application.WriteError("Failed to fix the navigation section parent folder '{0}'. {1}", child.ToString("B"), exc); } }
/// <summary> /// Fixes the navigation section upgrade identifier. /// </summary> /// <param name="name">The name.</param> /// <param name="upgradeId">The upgrade identifier.</param> /// <param name="alias">The alias.</param> /// <param name="nameSpace">The name space.</param> private static void FixNavSectionUpgradeId(string name, Guid upgradeId, string alias, string nameSpace) { if (string.IsNullOrEmpty(name)) { throw new ArgumentNullException("name"); } if (upgradeId == Guid.Empty) { throw new ArgumentNullException("upgradeId"); } if (string.IsNullOrEmpty(alias)) { throw new ArgumentNullException("alias"); } if (string.IsNullOrEmpty(nameSpace)) { throw new ArgumentNullException("nameSpace"); } try { const string commandText = @"-- Fix NavSection Update Id DECLARE @name BIGINT = dbo.fnAliasNsId( 'name', 'core', @tenantId ) DECLARE @isOfType BIGINT = dbo.fnAliasNsId( 'isOfType', 'core', @tenantId ) DECLARE @navSection BIGINT = dbo.fnAliasNsId( 'navSection', 'console', @tenantId ) DECLARE @resourceInFolder BIGINT = dbo.fnAliasNsId( 'resourceInFolder', 'console', @tenantId ) DECLARE @topMenu BIGINT = dbo.fnAliasNsId( 'topMenu', 'console', @tenantId ) DECLARE @alias BIGINT = dbo.fnAliasNsId( 'alias', 'core', @tenantId ) DECLARE @entityId BIGINT IF ( @context IS NOT NULL ) BEGIN DECLARE @contextInfo VARBINARY(128) = CONVERT( VARBINARY(128), @context ) SET CONTEXT_INFO @contextInfo END SELECT @entityId = e.Id FROM dbo.Entity e JOIN dbo.Data_NVarChar n ON e.Id = n.EntityId AND e.TenantId = n.TenantId AND n.FieldId = @name AND n.Data_StartsWith = @targetName JOIN dbo.Relationship t ON t.TenantId = n.TenantId AND t.TypeId = @isOfType AND t.FromId = n.EntityId AND t.ToId = @navSection JOIN dbo.Relationship r ON r.TenantId = n.TenantId AND r.TypeId = @resourceInFolder AND r.FromId = n.EntityId JOIN dbo.Relationship tt ON tt.TenantId = n.TenantId AND tt.TypeId = @isOfType AND tt.FromId = r.ToId AND tt.ToId = @topMenu WHERE e.TenantId = @tenantId AND e.UpgradeId <> @upgradeId IF ( @entityId IS NOT NULL ) BEGIN UPDATE dbo.Entity SET UpgradeId = @upgradeId WHERE Id = @entityId AND TenantId = @tenantId MERGE INTO [dbo].[Data_Alias] AS t USING ( SELECT @entityId AS [EntityId], @tenantId AS [TenantId], @alias AS [FieldId], @targetAlias AS [Data], @targetNamespace AS [Namespace], 0 AS [AliasMarkerId] ) s ON s.EntityId = t.EntityId AND s.TenantId = t.TenantId AND s.FieldId = t.FieldId WHEN NOT MATCHED THEN INSERT ( [EntityId], [TenantId], [FieldId], [Data], [Namespace], [AliasMarkerId] ) VALUES ( s.[EntityId], s.[TenantId], s.[FieldId], s.[Data], s.[Namespace], s.[AliasMarkerId] ); END"; long userId; RequestContext.TryGetUserId(out userId); using (DatabaseContext ctx = DatabaseContext.GetContext()) { using (DatabaseContextInfo.SetContextInfo("Fix nav section upgrade id")) using (var command = ctx.CreateCommand(commandText)) { ctx.AddParameter(command, "@tenantId", System.Data.DbType.Int64, RequestContext.TenantId); ctx.AddParameter(command, "@upgradeId", System.Data.DbType.Guid, upgradeId); ctx.AddParameter(command, "@targetName", System.Data.DbType.String, name); ctx.AddParameter(command, "@targetAlias", System.Data.DbType.String, alias); ctx.AddParameter(command, "@targetNamespace", System.Data.DbType.String, nameSpace); ctx.AddParameter(command, "@context", System.Data.DbType.AnsiString, DatabaseContextInfo.GetMessageChain(userId)); command.ExecuteNonQuery(); } } } catch (Exception exc) { EventLog.Application.WriteError("Failed to fix the navigation section '{0}'. {1}", name, exc); } }