File: D:/HostingSpaces/MBoogaard/oosting-horseriding.com/wwwroot/App_Code/CMS/UpgradeProcedure.txt
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Script.Serialization;
using System.Xml;
using System.Data.SqlClient;
using CMS.Base;
using CMS.CMSImportExport;
using CMS.Core;
using CMS.DataEngine;
using CMS.DocumentEngine;
using CMS.EventLog;
using CMS.FormEngine;
using CMS.Globalization;
using CMS.Helpers;
using CMS.IO;
using CMS.MacroEngine;
using CMS.Membership;
using CMS.Modules;
using CMS.PortalEngine;
using CMS.Search;
using CMS.Synchronization;
using CMS.URLRewritingEngine;
using CMS.WebAnalytics;
using CMS.WorkflowEngine;
using CMS.Taxonomy;
using System.Xml.Serialization;
#region "Code to bind to the ApplicationEvents using CMSModuleLoader"
/// <summary>
/// Upgrade loader
/// </summary>
[UpgradeLoader]
public partial class CMSModuleLoader
{
/// <summary>
/// Module registration
/// </summary>
private class UpgradeLoader : CMSLoaderAttribute
{
/// <summary>
/// Initializes the module
/// </summary>
public override void PreInit()
{
ApplicationEvents.UpdateData.Execute += Update;
}
/// <summary>
/// Updates the application data to a newer version if necessary
/// </summary>
private void Update(object sender, EventArgs eventArgs)
{
UpgradeProcedure.Update();
}
}
}
#endregion
/// <summary>
/// Class carrying the code to perform the upgrade procedure.
/// </summary>
public static class UpgradeProcedure
{
#region "Variables"
private const string FORM_DEFINITION_TABLE = "Temp_FormDefinition";
private const string FORM_DEFINITION_NAME_COLUMN = "ObjectName";
private const string FORM_DEFINITION_VALUE_COLUMN = "FormDefinition";
// Path to the upgrade package
private static string mUpgradePackagePath;
private static string mWebsitePath;
private static string mEventLogSource;
#endregion
#region "Properties"
/// <summary>
/// Gets the source text for event log records generated by upgrade actions
/// </summary>
private static string EventLogSource
{
get
{
return mEventLogSource ?? (mEventLogSource = string.Format("Upgrade to {0}", CMSVersion.MainVersion));
}
}
#endregion
#region "Main update method"
/// <summary>
/// Runs the update procedure.
/// </summary>
public static void Update()
{
if (DatabaseHelper.IsDatabaseAvailable && SystemContext.IsCMSRunningAsMainApplication)
{
try
{
string version = SettingsKeyInfoProvider.GetValue("CMSDataVersion");
switch (version.ToLowerCSafe())
{
case "8.2":
using (var context = new CMSActionContext())
{
context.LogLicenseWarnings = false;
UpgradeApplication(Upgrade82To90, "9.0", "Upgrade_82_90.zip");
}
break;
}
}
catch (Exception ex)
{
EventLogProvider.LogException(EventLogSource, "UPGRADE", ex);
}
}
}
#endregion
#region "General purpose - all versions methods"
private static void UpgradeApplication(Func<bool> versionSpecificMethod, string newVersion, string packageName)
{
// Increase the timeout for upgrade request due to expensive operations like macro signing and conversion (needed for large DBs)
HttpContext.Current.Server.ScriptTimeout = 14400;
EventLogProvider.LogInformation(EventLogSource, "START");
// Set the path to the upgrade package (this has to be done here, not in the Import method, because it's an async procedure without HttpContext)
mUpgradePackagePath = HttpContext.Current.Server.MapPath("~/CMSSiteUtils/Import/" + packageName);
mWebsitePath = HttpContext.Current.Server.MapPath("~/");
var dtm = new TableManager(null);
using (var context = new CMSActionContext())
{
context.DisableLogging();
context.CreateVersion = false;
context.LogIntegration = false;
if (dtm.TableExists(FORM_DEFINITION_TABLE))
{
UpdateClasses();
UpdateAlternativeForms();
DropTempDefinitionTable(dtm);
}
}
// Update all views
dtm.RefreshDocumentViews();
RefreshCustomViews(dtm);
// Set data version
SettingsKeyInfoProvider.SetGlobalValue("CMSDataVersion", newVersion);
SettingsKeyInfoProvider.SetGlobalValue("CMSDBVersion", newVersion);
// Clear hashtables
ModuleManager.ClearHashtables();
// Clear the cache
CacheHelper.ClearCache(null, true);
// Drop the routes
CMSDocumentRouteHelper.DropAllRoutes();
// Call version specific operations
if (versionSpecificMethod != null)
{
using (var context = new CMSActionContext())
{
context.DisableLogging();
context.CreateVersion = false;
context.LogIntegration = false;
versionSpecificMethod.Invoke();
}
}
// Import upgrade package with webparts, widgets...
UpgradeImportPackage();
// Run hotfix SQL scripts
RunHotfixSQL();
RefreshMacroSignatures();
EventLogProvider.LogInformation(EventLogSource, "FINISH");
}
/// <summary>
/// Refreshes all custom views.
/// </summary>
private static void RefreshCustomViews(TableManager tm)
{
tm.RefreshView("View_CMS_User");
tm.RefreshView("View_Community_Member");
tm.RefreshView("View_NewsletterSubscriberUserRole_Joined");
tm.RefreshView("View_Community_Group");
tm.RefreshView("View_Community_Friend_Friends");
tm.RefreshView("View_Community_Friend_RequestedFriends");
tm.RefreshView("View_OM_Contact_Activity");
tm.RefreshView("View_OM_Contact_Joined");
tm.RefreshView("View_OM_ContactGroupMember_ContactJoined");
tm.RefreshView("View_OM_Account_Joined");
tm.RefreshView("View_OM_Account_MembershipJoined");
tm.RefreshView("View_OM_ContactGroupMember_AccountJoined");
}
/// <summary>
/// Update form definitions of classes (especially system tables).
/// </summary>
private static void UpdateClasses()
{
DataSet classes = GetFormDefinitions();
if (!DataHelper.DataSourceIsEmpty(classes))
{
foreach (DataRow row in classes.Tables[0].Rows)
{
string objectName = DataHelper.GetStringValue(row, FORM_DEFINITION_NAME_COLUMN);
string newDefinition = DataHelper.GetStringValue(row, FORM_DEFINITION_VALUE_COLUMN);
if (!string.IsNullOrEmpty(objectName) && !string.IsNullOrEmpty(newDefinition))
{
var dataClass = DataClassInfoProvider.GetDataClassInfo(objectName);
if (dataClass != null)
{
var newVersionFi = new FormInfo(newDefinition);
var oldVersionFi = new FormInfo(dataClass.ClassFormDefinition);
// Get removed system fields
var removedfields = GetRemovedSystemFields(oldVersionFi, newVersionFi);
if (removedfields != null)
{
// Remove the system fields from class's alt.forms
foreach (var field in removedfields)
{
FormHelper.RemoveFieldFromAlternativeForms(dataClass, field, 0);
}
}
// Copy custom fields only for system tables
if (dataClass.ClassShowAsSystemTable)
{
CopyCustomFields(oldVersionFi, newVersionFi, false, true);
}
// Save the modified form definition
dataClass.ClassFormDefinition = newVersionFi.GetXmlDefinition();
// Update the scheme
dataClass.ClassXmlSchema = new TableManager(dataClass.ClassConnectionString).GetXmlSchema(dataClass.ClassTableName);
// Update search settings
dataClass.ClassSearchSettings = SearchHelper.CleanSearchSettings(dataClass);
// Save the new definition
dataClass.Update();
}
}
}
}
}
/// <summary>
/// Updates an existing alternative forms form definitions. Appends existing custom fields to new version definitions.
/// </summary>
private static void UpdateAlternativeForms()
{
DataSet classes = GetFormDefinitions(true);
if (!DataHelper.DataSourceIsEmpty(classes))
{
foreach (DataRow row in classes.Tables[0].Rows)
{
string objectName = DataHelper.GetStringValue(row, FORM_DEFINITION_NAME_COLUMN);
string newDefinition = DataHelper.GetStringValue(row, FORM_DEFINITION_VALUE_COLUMN);
if (!string.IsNullOrEmpty(objectName) && !string.IsNullOrEmpty(newDefinition))
{
var altForm = AlternativeFormInfoProvider.GetAlternativeFormInfo(objectName);
if (altForm != null)
{
var mainDci = DataClassInfoProvider.GetDataClassInfo(altForm.FormClassID);
var classFormDefinition = mainDci.ClassFormDefinition;
if (altForm.FormCoupledClassID > 0)
{
// If coupled class is defined combine form definitions
var coupledDci = DataClassInfoProvider.GetDataClassInfo(altForm.FormCoupledClassID);
if (coupledDci != null)
{
classFormDefinition = FormHelper.MergeFormDefinitions(classFormDefinition, coupledDci.ClassFormDefinition);
}
}
var oldVersionDefinition = FormHelper.MergeFormDefinitions(classFormDefinition, altForm.FormDefinition);
var newVersionDefinition = FormHelper.MergeFormDefinitions(classFormDefinition, newDefinition);
var newVersionFi = new FormInfo(newVersionDefinition);
var oldVersionFi = new FormInfo(oldVersionDefinition);
CopyCustomFields(oldVersionFi, newVersionFi, true, mainDci.ClassShowAsSystemTable);
// Save the modified form definition
altForm.FormDefinition = FormHelper.GetFormDefinitionDifference(classFormDefinition, newVersionFi.GetXmlDefinition(), true);
altForm.Update();
}
}
}
}
}
/// <summary>
/// Copies custom fields from old version of form definition to the new form definition.
/// </summary>
/// <param name="oldVersionFi">Old version form definition</param>
/// <param name="newVersionFi">New version form definition</param>
/// <param name="overwrite">Indicates whether existing fields should be overwritten. Alternative form fields need to be overwritten due to the combination with upgraded class form.</param>
/// <param name="isSystemTable">Indicates whether the class is customizable.</param>
private static void CopyCustomFields(FormInfo oldVersionFi, FormInfo newVersionFi, bool overwrite, bool isSystemTable)
{
// Remove all system fields from old definition to get only custom fields
// Remove all dummy fields from old definition for non-customizable classes (Since v9 is condition f => f.System sufficient because dummy fields created in development mode are system)
// * Dummy field in alternative forms are not marked as system in version < v9 and should be updated. Without this condition the old version of dummy field was used instead of new one.
// * Dummy field is not removed from customizable classes due to possible customization.
oldVersionFi.RemoveFields(f => f.System || (f.IsDummyField && !isSystemTable));
// Combine forms so that custom fields from old definition are appended to the new definition
newVersionFi.CombineWithForm(oldVersionFi, new CombineWithFormSettings
{
IncludeCategories = false,
RemoveEmptyCategories = true,
OverwriteExisting = overwrite
});
}
/// <summary>
/// Returns list with names of system fields which were removed to the new version.
/// </summary>
/// <param name="oldDefinition">Old form definition</param>
/// <param name="newDefinition">New form definition</param>
private static IEnumerable<string> GetRemovedSystemFields(FormInfo oldDefinition, FormInfo newDefinition)
{
if ((oldDefinition != null) && (newDefinition != null))
{
var oldSystemFields = oldDefinition.ItemsList.OfType<FormFieldInfo>().Where(f => f.System).Select(f => f.Name);
var newSystemFields = newDefinition.ItemsList.OfType<FormFieldInfo>().Where(f => f.System).Select(f => f.Name);
// Get difference of the sets
return oldSystemFields.Except(newSystemFields);
}
return null;
}
/// <summary>
/// Returns dataset with class names (or alt.form full names) and form definitions which should be used for the upgrade.
/// </summary>
/// <param name="getAltForms">Indicates if alt.form definitions should be returned</param>
private static DataSet GetFormDefinitions(bool getAltForms = false)
{
string queryText = String.Format("SELECT [{0}], [{1}] FROM [{2}] WHERE {3}", FORM_DEFINITION_NAME_COLUMN, FORM_DEFINITION_VALUE_COLUMN, FORM_DEFINITION_TABLE, getAltForms ? "IsAltForm = 1" : "IsAltForm = 0 OR IsAltForm IS NULL");
DataSet ds = null;
try
{
ds = ConnectionHelper.ExecuteQuery(queryText, null, QueryTypeEnum.SQLQuery);
}
catch (Exception ex)
{
EventLogProvider.LogException(EventLogSource, "GETFORMDEFINITION", ex);
}
return ds;
}
/// <summary>
/// Drops temporary table with classes' and alt.forms' form definitions.
/// </summary>
/// <param name="dtm">Table manager</param>
private static void DropTempDefinitionTable(TableManager dtm)
{
try
{
dtm.DropTable(FORM_DEFINITION_TABLE);
}
catch (Exception ex)
{
EventLogProvider.LogException(EventLogSource, "DROPTEMPTABLE", ex);
}
}
/// <summary>
/// Procedures which automatically imports the upgrade export package with all WebParts, Widgets, Reports and TimeZones.
/// </summary>
private static void UpgradeImportPackage()
{
// Import
try
{
RequestStockHelper.Remove("CurrentDomain", true);
var importSettings = new SiteImportSettings(MembershipContext.AuthenticatedUser)
{
DefaultProcessObjectType = ProcessObjectEnum.All,
SourceFilePath = mUpgradePackagePath,
WebsitePath = mWebsitePath
};
using (var context = new CMSActionContext())
{
context.DisableLogging();
context.CreateVersion = false;
context.LogIntegration = false;
ImportProvider.ImportObjectsData(importSettings);
// Regenerate time zones
TimeZoneInfoProvider.GenerateTimeZoneRules();
// Delete the files for separable modules which are not install and therefore not needed
DeleteWebPartsOfUninstalledModules();
ImportMetaFiles(Path.Combine(mWebsitePath, "App_Data\\CMSTemp\\Upgrade"));
}
}
catch (Exception ex)
{
EventLogProvider.LogException(EventLogSource, "IMPORT", ex);
}
}
/// <summary>
/// Refreshes macro signatures in all object which can contain macros.
/// </summary>
private static void RefreshMacroSignatures()
{
// Get object types
var objectTypes = new List<string> {
TransformationInfo.OBJECT_TYPE,
UIElementInfo.OBJECT_TYPE,
FormUserControlInfo.OBJECT_TYPE,
SettingsKeyInfo.OBJECT_TYPE,
AlternativeFormInfo.OBJECT_TYPE,
DataClassInfo.OBJECT_TYPE, // Process all data classes just through general object type to avoid duplicities
PageTemplateInfo.OBJECT_TYPE,
LayoutInfo.OBJECT_TYPE,
CssStylesheetInfo.OBJECT_TYPE,
WorkflowActionInfo.OBJECT_TYPE,
};
var admin = UserInfoProvider.AdministratorUserName;
foreach (string type in objectTypes)
{
try
{
using (var context = new CMSActionContext())
{
context.DisableLogging();
context.CreateVersion = false;
context.LogIntegration = false;
var infos = new InfoObjectCollection(type);
foreach (var info in infos)
{
MacroSecurityProcessor.RefreshSecurityParameters(info, admin, true);
}
}
}
catch (Exception ex)
{
EventLogProvider.LogException(EventLogSource, "REFRESHMACROSIGNATURES", ex, 0, "Type: " + type);
}
}
}
/// <summary>
/// Deletes the files for separable modules which are not install and therefore not needed.
/// </summary>
private static void DeleteWebPartsOfUninstalledModules()
{
var webPartsPath = mWebsitePath + "CMSWebParts\\";
var files = new List<string>();
var separableModules = new List<string>
{
ModuleName.BIZFORM,
ModuleName.BLOGS,
ModuleName.COMMUNITY,
ModuleName.ECOMMERCE,
ModuleName.EVENTMANAGER,
ModuleName.FORUMS,
ModuleName.MEDIALIBRARY,
ModuleName.MESSAGEBOARD,
ModuleName.MESSAGING,
ModuleName.NEWSLETTER,
ModuleName.NOTIFICATIONS,
ModuleName.ONLINEMARKETING,
ModuleName.POLLS,
ModuleName.REPORTING,
ModuleName.STRANDSRECOMMENDER,
ModuleName.CHAT,
};
foreach (var separableModule in separableModules)
{
// Add files from this folder to the list of files to delete if the module is not installed
if (!ModuleEntryManager.IsModuleLoaded(separableModule))
{
var folderName = GetWebPartFolderName(separableModule);
files.AddRange(GetAllFiles(webPartsPath + folderName));
}
}
// Remove web parts for separated modules
foreach (String file in files)
{
try
{
File.Delete(file);
}
catch (Exception ex)
{
EventLogProvider.LogException(EventLogSource, "DELETEWEBPARTS", ex, 0, "File: " + file);
}
}
}
/// <summary>
/// Returns list of all files in given folder (recursively, from all subdirectories as well).
/// </summary>
/// <param name="folder">Folder to search in</param>
private static List<String> GetAllFiles(String folder)
{
var files = new List<string>();
if (Directory.Exists(folder))
{
files.AddRange(Directory.GetFiles(folder));
var dirs = Directory.GetDirectories(folder);
foreach (string dir in dirs)
{
files.AddRange(GetAllFiles(dir));
}
}
return files;
}
/// <summary>
/// For given module returns it's folder name within CMSWebParts folder.
/// </summary>
/// <param name="moduleName">Name of the module</param>
/// <returns></returns>
private static string GetWebPartFolderName(string moduleName)
{
// Handle exceptions
switch (moduleName)
{
case ModuleName.BIZFORM:
return "BizForms";
case ModuleName.BLOGS:
return "Blogs";
case ModuleName.NEWSLETTER:
return "Newsletters";
}
// By default, trim "CMS." prefix from module name which will give us folder name withing CMSWebParts directory
return moduleName.Substring(4);
}
/// <summary>
/// Imports default metafiles which were changed in the new version.
/// </summary>
/// <param name="upgradeFolder">Folder where the generated metafiles.xml file is</param>
private static void ImportMetaFiles(string upgradeFolder)
{
try
{
// To get the file use Phobos - Generate files button, Metafile settings.
// Choose only those object types which had metafiles in previous version and these metafiles changed to the new version.
String xmlPath = Path.Combine(upgradeFolder, "metafiles.xml");
if (File.Exists(xmlPath))
{
XmlDocument xDoc = new XmlDocument();
xDoc.Load(xmlPath);
XmlNode metaFilesNode = xDoc.SelectSingleNode("MetaFiles");
if (metaFilesNode == null)
{
return;
}
String filesDirectory = Path.Combine(upgradeFolder, "Metafiles");
using (new CMSActionContext { LogEvents = false })
{
foreach (XmlNode metaFile in metaFilesNode)
{
// Load metafiles information from XML
if (metaFile.Attributes == null)
{
continue;
}
String objType = metaFile.Attributes["ObjectType"].Value;
String groupName = metaFile.Attributes["GroupName"].Value;
String codeName = metaFile.Attributes["CodeName"].Value;
String fileName = metaFile.Attributes["FileName"].Value;
String extension = metaFile.Attributes["Extension"].Value;
String fileGUID = metaFile.Attributes["FileGUID"].Value;
String title = (metaFile.Attributes["Title"] != null) ? metaFile.Attributes["Title"].Value : null;
String description = (metaFile.Attributes["Description"] != null) ? metaFile.Attributes["Description"].Value : null;
// Try to find correspondent info object
BaseInfo infoObject = BaseAbstractInfoProvider.GetInfoByName(objType, codeName);
if (infoObject == null)
{
continue;
}
int infoObjectId = infoObject.Generalized.ObjectID;
// Check if metafile exists
InfoDataSet<MetaFileInfo> metaFilesSet = MetaFileInfoProvider.GetMetaFilesWithoutBinary(infoObjectId, objType, groupName, "MetaFileGUID = '" + fileGUID + "'", null);
if (!DataHelper.DataSourceIsEmpty(metaFilesSet))
{
continue;
}
// Create new metafile if does not exists
String mfFileName = String.Format("{0}.{1}", fileGUID, extension.TrimStart('.'));
MetaFileInfo mfInfo = new MetaFileInfo(Path.Combine(filesDirectory, mfFileName), infoObjectId, objType, groupName);
mfInfo.MetaFileGUID = ValidationHelper.GetGuid(fileGUID, Guid.NewGuid());
// Set correct properties
mfInfo.MetaFileName = fileName;
if (title != null)
{
mfInfo.MetaFileTitle = title;
}
if (description != null)
{
mfInfo.MetaFileDescription = description;
}
// Save new meta file
MetaFileInfoProvider.SetMetaFileInfo(mfInfo);
}
// Remove existing files after successful finish
String[] files = Directory.GetFiles(upgradeFolder);
foreach (String file in files)
{
File.Delete(file);
}
}
}
}
catch (Exception ex)
{
EventLogProvider.LogException(EventLogSource, "IMPORTMETAFILES", ex);
}
}
#endregion
#region "Update from 8.2 to 9.0"
/// <summary>
/// Handles all the specific operations for upgrade from 8.2 to 9.0.
/// </summary>
private static bool Upgrade82To90()
{
UpgradeSocialMedia82To90();
UpgradeBlogClassesDefinition82To90();
RemoveWireFramePages82To90();
DeleteWireFramePageType82To90();
RemovedWireFrameWebPartsAndCategories82To90();
ExtractNewsletterUnsubscriptionsFromActivities();
MoveCleanOldShoppingCartSettingFromWebConfigToSettings82To90();
ProcessClickedLinkAndOpenedEmailGeneratedViaSubscriberLink();
UpdateTagInfoCodeNames();
UpgradeUserDashboardApplications();
return true;
}
#endregion
#region "Private methods"
/// <summary>
/// Upgrades Blog page types and removes fields for Trackbacks feature.
/// </summary>
private static void UpgradeBlogClassesDefinition82To90()
{
try
{
var pageTypeBlog = DataClassInfoProvider.GetDataClassInfo("cms.blog");
if (pageTypeBlog != null)
{
DocumentTypeHelper.RemoveColumnsFromPageType(pageTypeBlog, "BlogEnableTrackbacks");
}
var pageTypeBlogPost = DataClassInfoProvider.GetDataClassInfo("cms.blogpost");
if (pageTypeBlogPost != null)
{
DocumentTypeHelper.RemoveColumnsFromPageType(pageTypeBlogPost, "BlogPostPingedUrls", "BlogPostNotPingedUrls");
}
}
catch (Exception e)
{
EventLogProvider.LogException(EventLogSource, "UPGRADEBLOGPAGETYPES", e);
}
}
/// <summary>
/// Upgrades social media module
/// </summary>
private static void UpgradeSocialMedia82To90()
{
// Remove LinkedInRecommend button along with all dependencies.
RemoveWebParts(new List<string> { "5079A5D7-0361-4F89-8E61-F44AD66CEA11" });
}
/// <summary>
/// Removes list of the web parts
/// </summary>
/// <param name="webpartsList">List of web parts to remove</param>
private static void RemoveWebParts(IEnumerable<string> webpartsList)
{
foreach (var guid in webpartsList)
{
var webPart = WebPartInfoProvider.GetWebPartInfoByGUID(new Guid(guid));
if (webPart != null)
{
WebPartInfoProvider.DeleteWebPartInfo(webPart);
}
}
}
/// <summary>
/// Removes pages that uses wireframe page type.
/// </summary>
private static void RemoveWireFramePages82To90()
{
const string WIREFRAME_CLASS_NAME = "cms.wireframe";
// First, check whether wireframe data class exists and if it doesn't then skip removing wireframe pages.
if (DataClassInfoProvider.GetDataClassInfo(WIREFRAME_CLASS_NAME) == null)
{
return;
}
// Select wireframe pages
TreeProvider tp = new TreeProvider();
var wireframePages = tp.SelectNodes(WIREFRAME_CLASS_NAME)
.All()
.Path("/", PathTypeEnum.Children)
.OrderByDescending("NodeAliasPath");
foreach (TreeNode node in wireframePages)
{
DeleteDocumentSettings dds = new DeleteDocumentSettings
{
DeleteAllCultures = true,
DestroyHistory = true,
Node = node,
Tree = tp,
};
try
{
// Delete wireframe page and all its depending objects
DocumentHelper.DeleteDocument(dds);
}
catch (Exception ex)
{
EventLogProvider.LogException(EventLogSource, "DELETEWIREFRAMEPAGE", ex, node.NodeSiteID);
}
}
// Delete pages in recycle bin which were deleted earlier
var q = VersionHistoryInfoProvider.GetVersionHistories().WhereEquals("VersionClassID", DataClassInfoProvider.GetClasses().WhereEquals("ClassName", WIREFRAME_CLASS_NAME).AsSingleColumn().AsValue());
VersionManager vm = VersionManager.GetInstance(tp);
q.ForEachObject(vhi =>
{
try
{
vm.DestroyDocumentVersion(vhi.VersionHistoryID);
}
catch (Exception ex)
{
EventLogProvider.LogException(EventLogSource, "DELETEWIREFRAMEPAGEHISTORY", ex);
}
});
}
/// <summary>
/// Delete 'Wireframe' page type.
/// </summary>
private static void DeleteWireFramePageType82To90()
{
DeletePageType("cms.wireframe");
}
/// <summary>
/// Removes all wireframe web parts.
/// </summary>
private static void RemovedWireFrameWebPartsAndCategories82To90()
{
var webpartsList = new List<string>
{
"25E923B3-8D93-47C6-BE75-BC9C14DCE3F9", // Paragraph of text
"4E83FFC6-C7CA-43AA-BF44-2878AB740CA8", // Dialog
"FE1E3231-4137-42DE-A558-4A79B51AC6E7", // Breadcrumbs
"260BEE0B-99EF-4094-BD14-B459852ACA4F", // Button
"C49E608B-ED51-4B3B-A3AD-4C45B6DEEF30", // Menu bar
"06C3E7F9-3DAF-4CDB-8B07-67DB4CC920CB", // Image
"BB2E8F79-D2C4-4218-BDEA-9BDF3AFA41DD", // Note
"5BC544B6-FCAD-4AE5-96E7-119353C80474", // Label
"1024AC18-34DD-4418-A431-79C9562AD622", // Checkbox
"16263FC7-7007-4D23-B94F-29A59EFC22A9", // Radio button
"1F727857-E042-4210-8A94-22035D98F173", // Dropdown list
"3F9A3BA9-F885-467A-881D-E1B54277F2BB", // Checkbox list
"79CD1AC7-F598-4C13-9350-81E3E44C2AC2", // Radio button list
"B9D36520-3C25-4D7A-B5AB-D45478CA4C3C", // Text field / Textbox
"FAA59B7C-5E93-4CE1-85A0-4E4D03178B67", // Text area
"2CCE9045-DC25-46A2-9936-FAD2C63429A1", // Color picker
"D1E569E1-5D1C-4435-ADD9-2DDDE030D722", // Grid
"9C79EEE8-8EE9-4D38-894D-B6A1ADFFFB13", // Field set / Group
"B310F903-F1C2-49A6-B3C6-C472A75A1D0E", // Rectangle
"B03EEA82-81AB-4005-B19D-08F6FD42E81D", // Link bar
"DAB5055F-4794-4114-A202-6731F3F3ACAD", // Tag cloud
"05D0BCC0-7D46-43EF-ADC6-E4CCE1E9E9EE", // List
"DADE4EFB-D7C7-450D-8F84-C9AB9E265B29", // Icon
"76DD091C-F2BB-4EAE-B1CD-1F4EF8630110", // Multiline button
"CBC3A3A5-EDAD-4C43-9A4A-B5EE76E11DB9", // Note marker
"0AD8C3E1-39C5-4964-91D1-49FC4F1FAF35", // Horizontal slider
"71E69432-D82A-4E08-B5D2-CD46F9404FA5", // Tabs
"4A3A604A-8CBD-4A6E-91AC-06076AB852B4", // Wireframe area
"E3AAFF1C-E4CB-40EE-87B6-350411CE25F6", // Next page level
"CE9A73CC-C0AB-4CF3-9533-3530A71A3EF0", // Accordion
"68D1067A-0066-4C93-9B8A-A7B00A345F2D", // WYSIWYG Editor
"86BC31F6-CEDA-4D31-8CA5-D27604812198", // Multiline text
"8D798009-B4C2-4EBC-B84A-52392E0D98BA", // Button / Tab bar
"4D89268D-546D-4AAF-906E-C7E8967B5C96", // iPhone
"3101271E-BEBA-4A09-9D91-A39F1C313878", // iPhone keyboard
"98A14FD4-CAFF-487A-A3A7-DF19BC8C5699", // iPad
"AB643ACA-3590-4EE2-AC1F-28FC70E5E6EB", // Calendar
"08FF3141-112D-472F-8164-C160CC5B861B", // Bar chart
"F9FF7049-0EA0-40D7-9C4C-78F77C6BCC8B", // Column chart
"3D8EFD1C-4B96-4969-98A8-FC06DB88C81C", // Pie chart
"5AC875A5-6B74-4276-A355-84DF943FD169", // Area chart
"33BC09AC-1F2F-40A6-A8B2-5214A5C51A48", // Line chart
"754FC5C2-446A-4FE1-8790-75351B41F103", // Image carousel
"AEE34C85-993B-40CC-91A4-AB4DBACBED79", // Web camera
"A77C87A2-E988-496D-A6C4-E885446B6524", // Link
"FB403D35-55B7-4D2E-B053-1F19EE94DD79", // Title / header
"C1FE8B58-5078-4C4E-9686-B05713D44C4C", // Subtitle / Subheader
"B99A612B-25E7-439D-B547-9D10C72FD77B", // Date/time picker
"687DBDB7-120B-4DA2-8F15-CDFA28E7E508", // Search box
"3CCC0450-2281-4544-AF9A-4262944D5A0C", // Numeric up/down
"7C75EE16-3E1A-4F0D-A97E-F0E248CAE7D5", // Horizontal rule
"ACFA10B7-F22D-4F76-8409-3659A5E81187", // Vertical rule
"EB24D055-E8BE-4361-8C88-23643A10BF08", // Horizontal splitter
"5A9A7F09-66A6-4158-B95E-166896CBAB2B", // Vertical splitter
"51DB35EA-2F04-40C5-862B-EA24E91CACC2", // WYSIWYG Toolbar
"AD447470-296D-4FBA-83B0-952430906065", // Icon with label
"81E1D41C-7A77-4497-BCB1-8FB6A9447D19", // Vertical slider
"BEF0643D-9728-4A83-ABCA-24FC9145793E", // Progress bar
"0EA8F655-350D-4A7D-BD77-2AD9B342E42D", // Horizontal scrollbar
"4E79F21B-4960-4A2D-BBC3-521A6FD00AC1", // Vertical scrollbar
"4FF11A04-1932-43C5-B9FB-DFD8D567063B", // Tree pane
};
RemoveWebParts(webpartsList);
DeleteWireFrameWebPartCategories82To90();
}
/// <summary>
/// Deletes a given page type completely.
/// </summary>
/// <param name="className">Page type name</param>
private static void DeletePageType(string className)
{
DataClassInfo dci = DataClassInfoProvider.GetDataClassInfo(className);
if (dci == null)
{
return;
}
try
{
// Delete data class itself
dci.Destroy();
// Destroy its history
ObjectVersionManager.DestroyObjectHistory("cms.documenttype", dci.ClassID);
}
catch (Exception ex)
{
EventLogProvider.LogException(EventLogSource, "DELETEPAGETYPE", ex, 0, String.Format("Couldn't delete page type '{0}'.", dci.ClassName));
}
}
public static void ExtractNewsletterUnsubscriptionsFromActivities()
{
if (!ModuleEntryManager.IsModuleLoaded(ModuleName.NEWSLETTER))
{
return;
}
var activitiesQuery = new ObjectQuery(PredefinedObjectType.ACTIVITY)
.Source(s => s.Join("OM_Contact", "ActivityActiveContactID", "ContactID"))
.WhereEquals("ActivityType", PredefinedActivityType.NEWSLETTER_UNSUBSCRIBING)
.WhereNotEmpty("ContactEmail")
.Columns("ContactEmail", "ActivitySiteID", "ActivityCreated", "ActivityItemID")
.Distinct();
var activities = activitiesQuery.Select(row => new
{
SiteID = DataHelper.GetIntValue(row, "ActivitySiteID"),
ContactEmail = DataHelper.GetStringValue(row, "ContactEmail"),
ActivityCreated = DataHelper.GetDateTimeValue(row, "ActivityCreated"),
NewsletterID = DataHelper.GetIntValue(row, "ActivityItemID"),
});
var existingUnsubscriptionsByNewsletterID = new ObjectQuery(PredefinedObjectType.NEWSLETTERUNSUBSCRIPTION)
.WhereNotNull("UnsubscriptionNewsletterID")
.Select(row => new
{
Email = DataHelper.GetStringValue(row, "UnsubscriptionEmail"),
NewsletterID = DataHelper.GetIntValue(row, "UnsubscriptionNewsletterID"),
})
.GroupBy(unsubscription => unsubscription.NewsletterID)
.ToDictionary(group => group.Key, group => group.Select(u => u.Email).ToHashSet(StringComparer.InvariantCultureIgnoreCase));
foreach (var activity in activities)
{
if (existingUnsubscriptionsByNewsletterID.ContainsKey(activity.NewsletterID) && existingUnsubscriptionsByNewsletterID[activity.NewsletterID].Contains(activity.ContactEmail))
{
continue;
}
if (!ValidationHelper.IsEmail(activity.ContactEmail))
{
continue;
}
var unsubscriptionInfo = ModuleManager.GetObject(PredefinedObjectType.NEWSLETTERUNSUBSCRIPTION);
unsubscriptionInfo.SetValue("UnsubscriptionEmail", activity.ContactEmail.ToLowerInvariant());
unsubscriptionInfo.SetValue("UnsubscriptionNewsletterID", activity.NewsletterID);
unsubscriptionInfo.SetValue("UnsubscriptionSiteID", activity.SiteID);
unsubscriptionInfo.SetValue("UnsubscriptionCreated", activity.ActivityCreated);
unsubscriptionInfo.SetValue("UnsubscriptionGUID", Guid.NewGuid());
unsubscriptionInfo.Insert();
if (existingUnsubscriptionsByNewsletterID.ContainsKey(activity.NewsletterID))
{
existingUnsubscriptionsByNewsletterID[activity.NewsletterID].Add(activity.ContactEmail);
}
else
{
existingUnsubscriptionsByNewsletterID[activity.NewsletterID] = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase) { activity.ContactEmail };
}
}
}
/// <summary>
/// Deletes wireframe web part categories. Must be run after web parts were deleted.
/// </summary>
private static void DeleteWireFrameWebPartCategories82To90()
{
// Get all empty (= no web part contained) categories
var q = WebPartCategoryInfoProvider.GetCategories()
.WhereStartsWith("CategoryPath", "Wireframes/")
.WhereEquals("CategoryWebPartChildCount", 0)
.OrderBy(OrderDirection.Descending, "CategoryLevel")
.Columns("CategoryID", "CategoryDisplayName", "CategoryParentID", "CategoryPath");
q.ForEachObject(wpci =>
{
try
{
wpci.Delete();
}
catch (Exception ex)
{
EventLogProvider.LogException(EventLogSource, "DELETEWIREFRAMEWEBPARTCATEGORY", ex, 0, String.Format("Couldn't delete web part category '{0}' because it is not empty.", wpci.CategoryDisplayName));
}
});
}
/// <summary>
/// Moves setting value from web.config to the database table CMS_SettingsKey.
/// After the SQL upgrade only one global setting exists, so distribution to particular sites is not
/// necessary. If the value is not set in web.config file, default value is used (30 days).
/// </summary>
private static void MoveCleanOldShoppingCartSettingFromWebConfigToSettings82To90()
{
var settingValue = ValidationHelper.GetInteger(SettingsHelper.AppSettings["CMSShoppingCartExpirationPeriod"], 30);
SettingsKeyInfoProvider.SetValue("CMSShoppingCartExpirationPeriod", 0, settingValue);
}
/// <summary>
/// Post-processing of the clicked link/opened email records generated via subscriber link. Ensure valid emails from subscriber table.
/// </summary>
private static void ProcessClickedLinkAndOpenedEmailGeneratedViaSubscriberLink()
{
bool isSeparated = !String.IsNullOrEmpty(DatabaseSeparationHelper.ConnStringSeparate);
// If the database is separated, create temporary table with subscribers' ID and email
if (isSeparated)
{
// Get the subscribers with email from the default database
var subscribersQuery = new ObjectQuery("newsletter.subscriber")
.Columns("SubscriberID", "SubscriberEmail")
.WhereNull("SubscriberType").Or()
.WhereEquals("SubscriberType", "om.contact");
// Get the subscribers of user type from the default database
var subscribersFromUsersQuery = new ObjectQuery("newsletter.subscriber")
.Source(s => s.LeftJoin<UserInfo>("SubscriberRelatedID", "UserID"))
.Columns(new QueryColumn("SubscriberID"), new QueryColumn("Email").As("SubscriberEmail"))
.WhereEquals("SubscriberType", "cms.user")
.WhereNotNull("Email");
DataSet subscribers = subscribersQuery.Union(subscribersFromUsersQuery);
const string createTempTableScript =
@"
CREATE TABLE [Temp_Newsletter_Subscriber]
(
[SubscriberEmail] [nvarchar] (400),
[SubscriberID] [int] NOT NULL
) ON [PRIMARY];
";
// Create temporary table with subscribers on the separated db
using (new CMSConnectionScope(DatabaseSeparationHelper.OM_CONNECTION_STRING, false, true))
{
ConnectionHelper.ExecuteQuery(createTempTableScript, null, QueryTypeEnum.SQLQuery);
}
// Fill the table with subscribers' data
using (var bulkCopy = new SqlBulkCopy(DatabaseSeparationHelper.ConnStringSeparate, SqlBulkCopyOptions.KeepIdentity))
{
bulkCopy.ColumnMappings.Add("SubscriberEmail", "SubscriberEmail");
bulkCopy.ColumnMappings.Add("SubscriberID", "SubscriberID");
bulkCopy.BulkCopyTimeout = 6000;
bulkCopy.DestinationTableName = "Temp_Newsletter_Subscriber";
bulkCopy.WriteToServer(subscribers.Tables[0]);
}
const string updateClicksScript =
@"
UPDATE Newsletter_ClickedLink
SET ClickedLinkEmail = SubscriberEmail
FROM Newsletter_ClickedLink
LEFT JOIN Temp_Newsletter_Subscriber
ON REPLACE(ClickedLinkEmail,'subscriberid_','') = Temp_Newsletter_Subscriber.SubscriberID
WHERE ClickedLinkEmail NOT LIKE '%@%' AND SubscriberEmail IS NOT NULL;
";
const string updateOpensScript =
@"
UPDATE Newsletter_OpenedEmail
SET OpenedEmailEmail = SubscriberEmail
FROM Newsletter_OpenedEmail
LEFT JOIN Temp_Newsletter_Subscriber
ON REPLACE(OpenedEmailEmail,'subscriberid_','') = SubscriberID
WHERE OpenedEmailEmail NOT LIKE '%@%' AND SubscriberEmail IS NOT NULL;
";
var existingIssueIDs = new ObjectQuery("newsletter.issue")
.Column("IssueID")
.GetListResult<int>();
string deleteOpensWithNonExistingIssues =
string.Format(@"
DELETE FROM [Newsletter_OpenedEmail]
WHERE [OpenedEmailIssueID] NOT IN ({0})
", string.Join(",", existingIssueIDs));
// Update the data in ClickedLink/OpenedEmail table using OM connection string (or default)
using (new CMSConnectionScope(DatabaseSeparationHelper.OM_CONNECTION_STRING, false, true))
{
ConnectionHelper.ExecuteQuery(updateClicksScript, null, QueryTypeEnum.SQLQuery);
ConnectionHelper.ExecuteQuery(updateOpensScript, null, QueryTypeEnum.SQLQuery);
ConnectionHelper.ExecuteQuery(deleteOpensWithNonExistingIssues, null, QueryTypeEnum.SQLQuery);
}
const string dropTempTableScript =
@"
DROP TABLE Temp_Newsletter_Subscriber;
";
const string deleteUnresolvedClicksScript =
@"
DELETE FROM Newsletter_ClickedLink WHERE ClickedLinkEmail LIKE 'subscriberid_%' OR ClickedLinkEmail = '';
";
const string deleteUnresolvedOpensScript =
@"
DELETE FROM Newsletter_OpenedEmail WHERE OpenedEmailEmail LIKE 'subscriberid_%' OR OpenedEmailEmail = '';
";
const string deleteDuplicatesScript =
@"
WITH NOE AS(
SELECT OpenedEmailID, OpenedEmailEmail, OpenedEmailIssueID, OpenedEmailTime,
RN = ROW_NUMBER() OVER (PARTITION BY OpenedEmailEmail, OpenedEmailIssueID ORDER BY OpenedEmailTime ASC)
FROM Newsletter_OpenedEmail
)
DELETE FROM NOE
WHERE RN > 1;";
// Delete the temporary table on the separated database and ClickedLinks/OpenedEmails with unresolved emails
using (new CMSConnectionScope(DatabaseSeparationHelper.OM_CONNECTION_STRING, false, false))
{
ConnectionHelper.ExecuteQuery(dropTempTableScript, null, QueryTypeEnum.SQLQuery);
ConnectionHelper.ExecuteQuery(deleteUnresolvedClicksScript, null, QueryTypeEnum.SQLQuery);
ConnectionHelper.ExecuteQuery(deleteUnresolvedOpensScript, null, QueryTypeEnum.SQLQuery);
ConnectionHelper.ExecuteQuery(deleteDuplicatesScript, null, QueryTypeEnum.SQLQuery);
}
// Update Issues with opened email count
var openedEmailsSummary = new ObjectQuery("newsletter.openedemail")
.Columns(new QueryColumn("OpenedEmailIssueID"), new AggregatedColumn(AggregationType.Count, "OpenedEmailIssueID").As("Count"))
.GroupBy("OpenedEmailIssueID");
const string createOpenedEmailsSummaryTempTableScript =
@"
CREATE TABLE [Temp_Opened_Summary]
(
[OpenedEmailIssueID] [int],
[Count] [int]
) ON [PRIMARY];
";
ConnectionHelper.ExecuteQuery(createOpenedEmailsSummaryTempTableScript, null, QueryTypeEnum.SQLQuery);
using (var bulkCopy = new SqlBulkCopy(ConnectionHelper.ConnectionString, SqlBulkCopyOptions.KeepIdentity))
{
bulkCopy.ColumnMappings.Add("OpenedEmailIssueID", "OpenedEmailIssueID");
bulkCopy.ColumnMappings.Add("Count", "Count");
bulkCopy.BulkCopyTimeout = 6000;
bulkCopy.DestinationTableName = "Temp_Opened_Summary";
bulkCopy.WriteToServer(openedEmailsSummary.Tables[0]);
}
const string updateIssueOpenedEmailsScript =
@"
UPDATE Newsletter_NewsletterIssue
SET IssueOpenedEmails = (
SELECT Count FROM Temp_Opened_Summary
WHERE OpenedEmailIssueID = IssueID);
";
ConnectionHelper.ExecuteQuery(updateIssueOpenedEmailsScript, null, QueryTypeEnum.SQLQuery);
const string dropOpenedEmailsSummaryTempTableScript =
@"
DROP TABLE Temp_Opened_Summary;
";
ConnectionHelper.ExecuteQuery(dropOpenedEmailsSummaryTempTableScript, null, QueryTypeEnum.SQLQuery);
}
else
{
const string updateClicksScript =
@"
UPDATE Newsletter_ClickedLink
SET ClickedLinkEmail = ISNULL(SubscriberEmail, Email)
FROM Newsletter_ClickedLink
LEFT JOIN Newsletter_Subscriber
ON REPLACE(ClickedLinkEmail,'subscriberid_','') = Newsletter_Subscriber.SubscriberID
LEFT JOIN CMS_User
ON (UserID = SubscriberRelatedID AND SubscriberType = 'cms.user')
WHERE ClickedLinkEmail NOT LIKE '%@%' AND (SubscriberEmail IS NOT NULL OR Email IS NOT NULL);
";
const string deleteUnresolvedClicksScript =
@"
DELETE FROM Newsletter_ClickedLink WHERE ClickedLinkEmail LIKE 'subscriberid_%' OR ClickedLinkEmail = '';
";
const string updateOpensScript =
@"
UPDATE Newsletter_OpenedEmail
SET OpenedEmailEmail = SubscriberEmail
FROM Newsletter_OpenedEmail
LEFT JOIN Newsletter_Subscriber
ON REPLACE(OpenedEmailEmail,'subscriberid_','') = SubscriberID
WHERE OpenedEmailEmail NOT LIKE '%@%' AND SubscriberEmail IS NOT NULL;
";
const string deleteUnresolvedOpensScript =
@"
DELETE FROM Newsletter_OpenedEmail WHERE OpenedEmailEmail LIKE 'subscriberid_%' OR OpenedEmailEmail = '';
";
const string deleteDuplicatesScript =
@"
WITH NOE AS(
SELECT OpenedEmailID, OpenedEmailEmail, OpenedEmailIssueID, OpenedEmailTime,
RN = ROW_NUMBER() OVER (PARTITION BY OpenedEmailEmail, OpenedEmailIssueID ORDER BY OpenedEmailTime ASC)
FROM Newsletter_OpenedEmail
)
DELETE FROM NOE
WHERE RN > 1;
";
const string updateIssueOpenedEmailsScript =
@"
UPDATE Newsletter_NewsletterIssue
SET IssueOpenedEmails = (
SELECT COUNT(OpenedEmailIssueID) FROM Newsletter_OpenedEmail
WHERE OpenedEmailIssueID = IssueID
GROUP BY OpenedEmailIssueID);
";
// Update the data in ClickedLink/OpenEmail and delete unresolved emails
using (new CMSConnectionScope())
{
ConnectionHelper.ExecuteQuery(updateClicksScript, null, QueryTypeEnum.SQLQuery);
ConnectionHelper.ExecuteQuery(deleteUnresolvedClicksScript, null, QueryTypeEnum.SQLQuery);
ConnectionHelper.ExecuteQuery(updateOpensScript, null, QueryTypeEnum.SQLQuery);
ConnectionHelper.ExecuteQuery(deleteUnresolvedOpensScript, null, QueryTypeEnum.SQLQuery);
ConnectionHelper.ExecuteQuery(deleteDuplicatesScript, null, QueryTypeEnum.SQLQuery);
ConnectionHelper.ExecuteQuery(updateIssueOpenedEmailsScript, null, QueryTypeEnum.SQLQuery);
}
}
}
/// <summary>
/// TagInfo has new code name column, after upgrade we want that the code name will be similiar to the tag display name.
/// </summary>
private static void UpdateTagInfoCodeNames()
{
foreach (var tag in TagInfoProvider.GetTags().TypedResult)
{
var codeName = ValidationHelper.GetCodeName(tag.TagName);
tag.TagCodeName = codeName;
tag.Generalized.EnsureUniqueCodeName();
TagInfoProvider.SetTagInfo(tag);
}
}
/// <summary>
/// Upgrades user dashboard applications to the new format.
/// </summary>
private static void UpgradeUserDashboardApplications()
{
var userSettings = UserSettingsInfoProvider.GetUserSettings().WhereNotEmpty("UserDashboardApplications").ToList();
var serializer = new JavaScriptSerializer();
foreach (var userSetting in userSettings)
{
var userApplications = serializer.Deserialize<List<Guid>>(userSetting.UserDashboardApplications);
var newFormatUserDashboardApplications = serializer.Serialize(userApplications.Select(app => new { applicationGuid = app }));
userSetting.UserDashboardApplications = newFormatUserDashboardApplications;
UserSettingsInfoProvider.SetUserSettingsInfo(userSetting);
}
}
/// <summary>
/// Runs hotfix sql scripts
/// </summary>
private static void RunHotfixSQL()
{
string scriptsPath = SqlInstallationHelper.GetSQLInstallPath();
try
{
string pathToHotfixXML = Path.Combine(scriptsPath, "Hotfix\\Hotfix.xml");
bool dbSeparated = SqlInstallationHelper.DatabaseIsSeparated();
// Load hotfix sql scripts configuration
SQLSettings settings;
using (FileStream stream = FileStream.New(pathToHotfixXML, FileMode.Open))
{
XmlSerializer serializer = new XmlSerializer(typeof(SQLSettings));
settings = (SQLSettings)serializer.Deserialize(stream.SystemStream);
}
// Process and run all loaded scripts
settings.Scripts = settings.Scripts.OrderBy(s => s.SQLLaunchOrder).ToList();
foreach (SQLScript sqlScript in settings.Scripts)
{
if (!dbSeparated)
{
sqlScript.ConnectionStringName = ConnectionHelper.DEFAULT_CONNECTIONSTRING_NAME;
}
sqlScript.ConnectionString = ConnectionHelper.GetConnectionString(sqlScript.ConnectionStringName, false);
sqlScript.SQLFilePath = Path.Combine(scriptsPath, "Hotfix\\" + sqlScript.SQLFileName);
RunSQLScript(sqlScript);
}
}
catch (Exception ex)
{
EventLogProvider.LogException("Upgrade - Applying hotfix sql scripts", "Upgrade", ex);
}
finally
{
// Dispose the zip storage provider to release memory and the file
if (ZipStorageProvider.IsZipFolderPath(scriptsPath))
{
ZipStorageProvider.Dispose(scriptsPath);
}
}
}
/// <summary>
/// Runs given hotfix script using the specified connection string.
/// </summary>
/// <param name="sqlScript">Sql script to run</param>
private static void RunSQLScript(SQLScript sqlScript)
{
using (IDataConnection conn = ConnectionHelper.GetConnection(sqlScript.ConnectionString))
{
conn.Open();
string query = File.ReadAllText(sqlScript.SQLFilePath);
string[] sqlParts = query.Split(new [] { "GO" + Environment.NewLine, "GO\n" }, StringSplitOptions.RemoveEmptyEntries);
foreach (string sql in sqlParts)
{
try
{
// Run part of SQL script
conn.ExecuteNonQuery(sql, null, QueryTypeEnum.SQLQuery, false);
}
catch (Exception ex)
{
EventLogProvider.LogException("Upgrade - Applying hotfix sql scripts", "Upgrade", ex);
}
}
}
}
#endregion
}