Compare commits

...

135 Commits

Author SHA1 Message Date
Shannon d50e49ad37 Fixes: U4-7120 SQL Fail upgrading om 7.2.4 to 7.3 - due to index on master col 2015-09-29 11:55:21 +02:00
Shannon c8dc10f2e3 Fixes: U4-7159 XSS issue with EditMacro.aspx 2015-09-29 11:44:22 +02:00
Shannon 0504663814 Fixes: U4-7158 Fix OrderBy query string parameter which can allow SQL Injection 2015-09-29 11:28:12 +02:00
Shannon 62611a7255 U4-7157 remove ~/umbraco/webservice.asmx 2015-09-29 10:54:56 +02:00
Shannon 407cd0ca60 Streamlines TypeFinder with better lock and an error check on app_code which could otherwise bring down the app 2015-09-25 11:29:09 +02:00
Per Ploug b384f1b0c3 adds a private identifier validation method
Fixes issue with Umbraco Forms not being able to save
2015-09-24 11:39:43 +02:00
Shannon 14c4e9dda7 Fixes upgrade issue for when the same alias is used between content types and media types. 2015-09-23 11:29:29 +02:00
Sebastiaan Janssen 12fb549469 Merge pull request #798 from JimBobSquarePants/feature/update-imageprocessor
Update ImageProcessor dependency for core
2015-09-23 10:56:25 +02:00
James Jackson-South 2599fdb1d2 Fix missing project reference 2015-09-23 18:06:49 +10:00
Sebastiaan Janssen d05395075d Indentation 2015-09-23 08:34:55 +02:00
Sebastiaan Janssen 664ecd6bb7 Merge pull request #797 from JimBobSquarePants/feature/nuget-restore
Add custom repo package restore
2015-09-23 08:33:56 +02:00
James Jackson-South 6b639e940c Update ImageProcessor dependency for core
An update to U4-7053. Reduced memory usage plus web optimised images.
2015-09-23 16:05:07 +10:00
James Jackson-South 5b688d42ba Add custom repo package resotore
Adds the ability for contributors to pull the Umbraco specific Nuget
packages from the Myget repository using package restore.

https://docs.nuget.org/consume/nuget-config-file
2015-09-23 15:56:05 +10:00
Stephan 3124ea4e67 U4-7129 - BatchedDatabaseServerMessenger degraded non-batching mode when no context 2015-09-22 18:20:49 +02:00
Stephan e9afa78444 U4-7124 - add initial migration as part of BaseDataCreation 2015-09-22 18:16:35 +02:00
Stephan ef6fd54af3 Merge pull request #795 from Jeavon/U4-6784
Fix for U4-6784 Multiple Media Picker
2015-09-22 15:37:34 +02:00
Shannon 03f68cefb7 performs a fallback check for HttpContext in the batched server messengers in some cases where cache refreshers are executed on async threads... though there's not much we can do about when they are fired on background threads. 2015-09-22 14:39:55 +02:00
Shannon f8fa7df3f3 Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2015-09-22 12:19:22 +02:00
Shannon 25cfe0193c adds detailed shutdown info to logs by default 2015-09-22 12:19:14 +02:00
Stephan 3612780d15 git-ignore loader.dev.js 2015-09-22 11:18:06 +02:00
Jeavon 7d8247047b Fix for U4-6784 Multiple Media Picker - Failed to retrieve entity data for ids 2015-09-21 14:23:36 +01:00
Sebastiaan Janssen 91a1955454 Make sure to redirect to the current version of HTML Agility Pack 2015-09-17 12:20:11 +02:00
Sebastiaan Janssen 1f3c396c5b Using protocol-relative URLs is an antipattern, just use https if you know it exists 2015-09-16 19:00:14 +02:00
Sebastiaan Janssen b9dd0ab1a9 Bump version 2015-09-16 18:58:45 +02:00
Shannon 779dd26527 Fixes: U4-6969 Property label localization in 7.3 always uses en-US locale 2015-09-16 15:22:40 +02:00
Shannon 65969e22a0 removes commented out code 2015-09-16 14:33:30 +02:00
Shannon 23f7a4e53f Set min password length is 8 characters by default for release 2015-09-16 14:32:56 +02:00
Stephan 5b1ed8bef5 U4-7108 - fix ContentTypeService.GetMediaType(guid) 2015-09-16 11:08:18 +02:00
Stephan 583ae2df11 Bugfix 2015-09-15 10:52:32 +02:00
Stephan 14cd1e7a76 Bugfix SqlSyntaxProvider date formatting 2015-09-15 10:49:41 +02:00
Sebastiaan Janssen 4572b55f98 U4-7029 Upgrading Umbraco will remove owin:startup key if configured differently
#U4-7029 Fixed
2015-09-15 10:17:31 +02:00
Stephan af2dbc7cd9 U4-6811 - bugfix preview set 2015-09-14 12:43:05 +02:00
Shannon 5d7ba5c842 fixes tests 2015-09-14 12:30:32 +02:00
Shannon bee59e39a0 Streamlines migration classes and ctor dependencies... before there was issues because the current db provider was not set correctly so migrations couldn't actually rely onthe CurrentDatabaseProvider property! 2015-09-14 12:01:48 +02:00
Shannon 8d24ac3651 Oops, fixes PK creation logic for MySQL (had the wrong boolean) 2015-09-14 10:33:37 +02:00
Shannon 7beb21ad66 Fixes upgrade issues with MySql, along with a few other things:
* All usages of getdate() are changed to the system value
* All usages of newid() are chagned to the system value
* Removes the hacks associated with the above
* Fixes the fluent migrations for table creation for mysql to not double create a PK
* Removes other system field values that actually don't do anthing and shouldn't be used
2015-09-11 17:49:47 +02:00
Shannon ed51dbaf85 Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2015-09-11 13:55:21 +02:00
Shannon 488ba05eda Fixes upgrade issues with SQLCE and DateTime:
* DateTime's during migrations are formatted in a very explicit way
* Migration's that need to execute multiple statements are fixed in SQLCE by splitting on GO
2015-09-11 13:55:13 +02:00
Stephan 5dac5ed88b U4-7084 - fix XmlExtensions, publishing a package works 2015-09-11 13:17:07 +02:00
Shannon 4bb89c1827 Fixes: U4-7090 Upgrade error with dates 2015-09-11 11:49:37 +02:00
Shannon Deminick 647c7a6ce0 Merge pull request #788 from dampee/fixes/U4-7087
U4-7087 make pageId getter public to be able to unittest
2015-09-10 19:09:23 +02:00
Damiaan 6d5a8c0db7 U4-7087 make pageId getter public to be able to unittest 2015-09-10 18:11:18 +02:00
Stephan 3314ab026b U4-7083 - filesystems, polish, fix, and back-compat 2015-09-10 14:20:21 +02:00
Stephan 8b612a1047 Use SaveFileController for stylesheets too 2015-09-10 14:19:56 +02:00
Stephan 28ecf79643 files editor xss 2015-09-10 11:20:01 +02:00
Stephan 8f78ba8b97 Revert "TEMP move stylesheet..." (pushed by mistake)
This reverts commit 7e1a11373b.
2015-09-10 11:14:23 +02:00
Stephan 94b0870a53 U4-6992 - fix db migrations (for real) 2015-09-10 10:47:30 +02:00
Stephan b9ff056b61 Revert "U4-6992 - fix db migrations"
This reverts commit 406d172169.
2015-09-10 10:19:28 +02:00
Stephan 7e1a11373b TEMP move stylesheet editing to filesystem 2015-09-10 10:12:25 +02:00
Stephan 200625aa3a SaveFileController can also save stylesheets (not used at the moment) 2015-09-10 10:04:55 +02:00
Shannon f1e52c5ad8 fixes failing test 2015-09-10 00:18:58 +02:00
Shannon 1217e64532 Adds another migration to fix corrupted data very old dbs 2015-09-10 00:16:35 +02:00
Shannon c454d022dc changes code migration to use the db paramet in the lambda 2015-09-09 23:30:14 +02:00
Shannon c4b8dcd88b Fixes: U4-7079 Upgrade issue from an older version 2015-09-09 23:20:46 +02:00
Shannon 3a62fb5900 fixes script editor xss 2015-09-09 22:00:29 +02:00
Shannon d127856726 fixes script editor xss 2015-09-09 21:52:52 +02:00
Shannon 02e9866398 Fixes regression issue with xss 2015-09-09 21:41:06 +02:00
Stephan ed8c9daa8a Merge pull request #787 from vnbaaij/patch-2
Remove duplicated code in UmbracoApplicationBase
2015-09-09 16:37:10 +02:00
Stephan 59ec709c69 U4-7048 - more filesystems cleanup 2015-09-09 16:32:45 +02:00
Vincent Baaij 68fa22ba9b Update UmbracoApplicationBase.cs
There were two (almost identical) unhandled exception handlers in the code. Think it was caused  by merge conflict
2015-09-09 15:56:00 +02:00
Stephan e8b2f3cd0b U4-7078 - empty recycle bin with content with public access rules 2015-09-09 13:02:21 +02:00
Shannon 74eb69534d Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2015-09-09 10:20:26 +02:00
Shannon 710bc7ed7c fixes minor potential xss issue with stylesheets editor 2015-09-09 10:19:57 +02:00
Shannon Deminick be17a6e186 Merge pull request #756 from haileqsr/fixes
U4-6955: Issue with stripping modifiers with no trailing characters
2015-09-08 19:03:16 +02:00
Stephan b7eb6303ec U4-7076 - fix xml cache corruption when publishing with children 2015-09-08 18:38:52 +02:00
Shannon 4d012ee1e1 Ensures that any stale old temp upload files are removed any time media is uploaded. 2015-09-08 18:33:43 +02:00
Stephan e3a73465f7 U4-7048 - fix tests 2015-09-08 18:10:46 +02:00
Stephan 6b5057b870 U4-7048 - more filesystems cleanup 2015-09-08 17:48:26 +02:00
Stephan e577648efd U4-7048 - refresh IFile instances from disk 2015-09-08 11:34:34 +02:00
Shannon b3664d2391 Fixes: U4-7059 SQL problem upgrading from 7.2.8 to 7.3.0 RC 2015-09-07 23:45:55 +02:00
Shannon 3dc4059036 fixes: U4-6941 Can't edit masterpages templates in 7.3.0 beta3 2015-09-07 20:28:56 +02:00
Shannon 6d6b2f72b6 fixes open redirect issue for schema less Urls 2015-09-07 20:15:10 +02:00
Stephan a542cf56d4 U4-7063 - Umbraco.TypedContent(ints) should not return nulls 2015-09-04 10:43:42 +02:00
Shannon 1fdb813d1d Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2015-09-03 16:49:14 +02:00
Shannon 6c3b63cf55 fixes issue with legacy dialogs not closing the nav 2015-09-03 16:32:25 +02:00
Stephan 6b195587c1 U4-7042 - fix root path for tests 2015-09-03 16:24:43 +02:00
Stephan d323b3c5c9 U4-7042 - use IFileService when editing scripts 2015-09-03 15:12:37 +02:00
Stephan b03d7884bb U4-7042 - bugfix the physical filesystem 2015-09-03 15:11:49 +02:00
Stephan 37e6e61eff Manual-merge pull request #750 dealing with U4-7060 2015-09-02 16:42:43 +02:00
Stephan 42e5b4e867 U4-7055 - encodeURIComponent queries in Examine dashboard 2015-09-02 15:19:37 +02:00
Stephan fc8c92e922 U4-7056 - sync BatchedDatabaseServerMessenger on all requests 2015-09-02 14:44:02 +02:00
Stephan 5d7cbd3477 U4-7038 - fix bugs + tests 2015-09-01 16:11:26 +02:00
Stephan 42b689867e U4-6992,U4-7046 - more fixes & tests 2015-09-01 15:46:58 +02:00
Sebastiaan Janssen d4fb28607d U4-7053 Update ImageProcessor dependency for core
#U4-7053 Fixed
2015-09-01 15:35:42 +02:00
Stephan dfbdf99bbc U4-7038 - IPublishedContentWithKey for medias 2015-09-01 15:00:31 +02:00
Stephan 7848ea5ec0 U4-7038 - IPublishedContentWithKey for contents, members 2015-09-01 15:00:27 +02:00
Claus 62afc06f56 Fixes: COU-162 Revision Name is Lowercase After Transfer
Removed lowercasing of urls routed through legacy iframe injection controller.
Regex for javascript handlers changed to ignore casing.
2015-09-01 14:30:30 +02:00
Stephan dbe2257b47 U4-7046 - fix DatabaseServerRegistrar issues 2015-09-01 13:16:58 +02:00
Shannon Deminick 2029bef6eb Merge pull request #771 from Jeavon/GetCropUrlFixes
Fix for U4-6995 Image Cropper does not use predefined crop ratio when only width or height is supplied
2015-09-01 11:29:45 +02:00
Shannon Deminick ffddb8faa0 Merge pull request #772 from danbramall/dev-v7
Rounds grid widths to 8 decimal places (like Bootstrap)
2015-09-01 11:13:13 +02:00
Shannon Deminick 456c89a5d5 Merge pull request #784 from umbraco/U4-6193
Fixes: U4-6193 Inserting an image into grid layout ignores alternativ…
2015-09-01 11:12:06 +02:00
Claus 37986f0ed5 Fixes: U4-6193 Inserting an image into grid layout ignores alternative text
AltText is used for alt tag instead of caption text which is used below the media.
Ensured the altText set in the dialog is saved to the value object.
2015-09-01 10:28:35 +02:00
Shannon b883c7cb11 Fixes: U4-6947 Don't ship unnecessary js files 2015-08-31 18:51:36 +02:00
Shannon 23a7e515f8 Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2015-08-31 18:04:23 +02:00
Shannon 05e17e1c7f Fixes: U4-6973 Given custom permissions user can create, but cannot save 2015-08-31 18:04:13 +02:00
Stephan 829942dcf9 Bugfix MediaService 2015-08-31 13:17:50 +02:00
Shannon 9ce1ea66dc Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2015-08-28 15:26:22 +02:00
Shannon d6d611d381 updates the data type view to be consistent with the rest 2015-08-28 15:25:35 +02:00
Shannon Deminick 7020e948b8 Merge pull request #780 from umbraco/COU-191
Fixes: COU-191 Creating a revision gives a reference not set error (7.3)
2015-08-28 13:35:07 +02:00
Stephan b96511d9d4 U4-6992 - fix tests 2015-08-28 13:28:03 +02:00
Stephan ed5ca49755 U4-6992 - update interfaces 2015-08-28 13:28:00 +02:00
Claus c1352e2ad6 Fixes: COU-191 Creating a revision gives a reference not set error (7.3)
If the typeInstance could not be cast to LegacyDialogTask, trying to set additionalValues caused a null exception.
Inserted a null check and then cast to ITaskReturnUrl instead to get the returnUrl.
2015-08-28 13:01:23 +02:00
Shannon 1a6988c2ea Fixes double event firing 2015-08-27 20:10:19 +02:00
Shannon 0cca63e646 Fixes up some unit tests 2015-08-27 19:19:05 +02:00
Shannon 05aa2aeb75 refactors new IDomainService to return attempt+status and raise events using event messages. 2015-08-27 18:43:54 +02:00
Shannon e3cc107bfa Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2015-08-27 18:33:48 +02:00
Shannon 4a59c27793 Refactors new IPublicAccessService to return Attempt+Result so we know what happened, also ensures events are firing with msgs (events were not firing at all before). 2015-08-27 18:33:38 +02:00
Shannon Deminick abde63ebee Merge pull request #768 from abryukhov/patch-3
ru.xml - newest 'member' and 'help' sections
2015-08-27 15:17:44 +02:00
Shannon Deminick 346fb471da Merge pull request #773 from bjarnef/dev-v7-additional-translations
Additional translations for members
2015-08-27 15:14:54 +02:00
Shannon d4c5a1ee1c Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2015-08-27 14:56:51 +02:00
Shannon e3598b99a5 Ensures tempdata is set on our member controllers in the correct place and ensures that the RegisterModel doesn't explicitly set the RedirectUrl because we want it to be empty by default. 2015-08-27 14:56:42 +02:00
Stephan ab32732f26 U4-6992 - cannot change app url provider once resolution is frozen 2015-08-27 13:18:18 +02:00
Stephan 3949cfa736 U4-6932 - cleanup 2015-08-27 13:11:16 +02:00
Stephan 406d172169 U4-6992 - fix db migrations 2015-08-27 13:08:50 +02:00
Stephan b550b9f9d1 U4-6932 - bugfix bulk processing in list view 2015-08-26 18:30:05 +02:00
Shannon Deminick 211268f210 Merge pull request #779 from SiroccoHub/dev-v7
Update Japanese resource XML for UI
2015-08-26 15:09:39 +02:00
arichika taniguchi 348a3e6692 Merge remote-tracking branch 'umbraco/dev-v7' into dev-v7 2015-08-26 21:54:43 +09:00
arichika taniguchi c3c63ce0e3 Update Japanese resource XML for UI
Update Japanese resource XML for UI
2015-08-26 21:33:35 +09:00
Stephan 20d8656237 U4-6992 - fix server registration for new LB 2015-08-26 14:00:56 +02:00
Stephan e114cbeeaf Persistence - add support for locking repositories 2015-08-26 14:00:53 +02:00
Stephan a6a6edb9f2 PetaPoco - add support for transaction level 2015-08-26 14:00:50 +02:00
Shannon Deminick 5cfb4f5122 Merge pull request #777 from umbraco/U4-6997
Fixes: U4-6997 Updating Public Access settings on a node should trigg…
2015-08-25 13:31:39 +02:00
Stephan eec11c8e5f U4-6990 - fix task scheduler 2015-08-25 11:59:56 +02:00
Claus 438dedd1ab Fixes: U4-6997 Updating Public Access settings on a node should trigger a re-render of the tree.
For some reason the ReloadActionNode does not work in this case. Updated to using SyncTree which works.
2015-08-25 11:26:43 +02:00
Stephan a950acbaba U4-7002 - ToAppRelative is too greedy 2015-08-24 17:28:04 +02:00
Claus f44875d072 Prevent internal member groups from showing up in group list on member properties.
Prevent internal member groups from showing up in the member group tree listing.
2015-08-24 16:14:29 +02:00
bjarnef d7360e7a41 Additional translations for members
Addtional translations for members, help dialog and a few updated in
da.xml
2015-08-23 16:49:53 +02:00
Dan Bramall bd56117c80 Rounds grid widths to 8 decimal places (like Bootstrap) to fix U4-6569 and U4-6357. 2015-08-20 22:08:31 +01:00
Jeavon Leopold 8ea99b9463 Adjust so that first crop isn't used for ratio when only a width or height parameter is passed into GetCropUrl 2015-08-20 10:22:15 +01:00
Jeavon Leopold bc20a48570 Tiny Stylecop bracket adjustment 2015-08-20 09:34:48 +01:00
Jeavon Leopold a17865683c Variable renaming 2015-08-20 09:33:12 +01:00
Jeavon Leopold 6f76ee384c Added some extra GetCropUrl tests as you can never have too many 2015-08-20 09:31:20 +01:00
Alexander Bryukhov 5167ba7aee ru.xml - newest 'member' and 'help' sections 2015-08-20 09:04:52 +06:00
Jeavon Leopold 3595dd3339 Adding checks for predefined crops that are still set to default and where a specific resize parameter has been passed into GetCropUrl so that output crop is in same ratio as the predefined crop 2015-08-19 16:54:03 +01:00
Hai Le 4697f2ecad Bug fix: Issue with stripping modifiers with no trailing characters after placeholder
When using a modifier with no trailing characters after the placeholder eg. setting a color style with #{0}.  The end selection is set to 0 resulting in the value also being stripped
2015-08-01 15:54:00 +10:00
269 changed files with 5127 additions and 3031 deletions
+1
View File
@@ -76,6 +76,7 @@ src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/umbraco.*
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/routes.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/app.dev.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/loader.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/loader.dev.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/main.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/app.js
+2 -2
View File
@@ -33,8 +33,8 @@
<dependency id="AutoMapper" version="[3.0.0, 3.1.0)" />
<dependency id="Newtonsoft.Json" version="[6.0.8, 7.0.0)" />
<dependency id="Examine" version="[0.1.68, 1.0.0)" />
<dependency id="ImageProcessor" version="[1.9.5, 3.0.0)" />
<dependency id="ImageProcessor.Web" version="[3.3.1, 5.0.0)" />
<dependency id="ImageProcessor" version="[2.3.0, 3.0.0)" />
<dependency id="ImageProcessor.Web" version="[4.4.0, 5.0.0)" />
<dependency id="semver" version="[1.1.2, 2.0.0)" />
<dependency id="Microsoft.AspNet.WebHelpers" version="[3.2.3, 4.0.0)" />
<dependency id="Microsoft.AspNet.WebPages.Data" version="[3.2.3, 4.0.0)" />
+1 -4
View File
@@ -22,10 +22,7 @@
<appSettings>
<add key="owin:appStartup" value="UmbracoDefaultOwinStartup" xdt:Locator="Match(key)" xdt:Transform="InsertIfMissing" />
</appSettings>
<appSettings>
<add key="owin:appStartup" value="UmbracoDefaultOwinStartup" xdt:Locator="Match(key)" xdt:Transform="SetAttributes" />
</appSettings>
<umbracoConfiguration xdt:Transform="InsertIfMissing">
<settings configSource="config\umbracoSettings.config" xdt:Locator="Match(configSource)" xdt:Transform="InsertIfMissing" />
<BaseRestExtensions configSource="config\BaseRestExtensions.config" xdt:Locator="Match(configSource)" xdt:Transform="InsertIfMissing" />
+1 -2
View File
@@ -1,3 +1,2 @@
# Usage: on line 2 put the release version, on line 3 put the version comment (example: beta)
7.3.0
RC
7.3.0
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="nuget.org" value="https://www.nuget.org/api/v2/" />
<add key="umbracocore" value="http://www.myget.org/f/umbracocore/" />
</packageSources>
</configuration>
+1 -1
View File
@@ -12,4 +12,4 @@ using System.Resources;
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("7.3.0")]
[assembly: AssemblyInformationalVersion("7.3.0-RC")]
[assembly: AssemblyInformationalVersion("7.3.0")]
+9 -12
View File
@@ -2,6 +2,7 @@
using System.Configuration;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.ObjectResolution;
@@ -259,22 +260,13 @@ namespace Umbraco.Core
{
get
{
// if initialized, return
if (_umbracoApplicationUrl != null) return _umbracoApplicationUrl;
// try settings
ServerEnvironmentHelper.TrySetApplicationUrlFromSettings(this, ProfilingLogger.Logger, UmbracoConfig.For.UmbracoSettings());
// and return what we have, may be null
ApplicationUrlHelper.EnsureApplicationUrl(this);
return _umbracoApplicationUrl;
}
set
{
_umbracoApplicationUrl = value;
}
}
internal string _umbracoApplicationUrl; // internal for tests
// ReSharper disable once InconsistentNaming
internal string _umbracoApplicationUrl;
private Lazy<bool> _configured;
internal MainDom MainDom { get; private set; }
@@ -379,6 +371,11 @@ namespace Umbraco.Core
internal set { _services = value; }
}
internal ServerRole GetCurrentServerRole()
{
var registrar = ServerRegistrarResolver.Current.Registrar as IServerRegistrar2;
return registrar == null ? ServerRole.Unknown : registrar.GetCurrentServerRole();
}
private volatile bool _disposed;
private readonly ReaderWriterLockSlim _disposalLocker = new ReaderWriterLockSlim();
@@ -24,7 +24,7 @@ namespace Umbraco.Core.Configuration
/// Gets the version comment (like beta or RC).
/// </summary>
/// <value>The version comment.</value>
public static string CurrentComment { get { return "RC"; } }
public static string CurrentComment { get { return ""; } }
// Get the version of the umbraco.dll by looking at a class in that dll
// Had to do it like this due to medium trust issues, see: http://haacked.com/archive/2010/11/04/assembly-location-and-medium-trust.aspx
+73 -68
View File
@@ -2,91 +2,96 @@
namespace Umbraco.Core
{
public static partial class Constants
{
/// <summary>
/// Defines the identifiers for Umbraco object types as constants for easy centralized access/management.
/// </summary>
public static class ObjectTypes
{
/// <summary>
/// Guid for a Content Item object.
/// </summary>
public const string ContentItem = "10E2B09F-C28B-476D-B77A-AA686435E44A";
public static partial class Constants
{
/// <summary>
/// Defines the identifiers for Umbraco object types as constants for easy centralized access/management.
/// </summary>
public static class ObjectTypes
{
/// <summary>
/// Guid for a Content Item object.
/// </summary>
public const string ContentItem = "10E2B09F-C28B-476D-B77A-AA686435E44A";
/// <summary>
/// Guid for a Content Item Type object.
/// </summary>
public const string ContentItemType = "7A333C54-6F43-40A4-86A2-18688DC7E532";
/// <summary>
/// Guid for a Content Item Type object.
/// </summary>
public const string ContentItemType = "7A333C54-6F43-40A4-86A2-18688DC7E532";
/// <summary>
/// Guid for the Content Recycle Bin.
/// </summary>
public const string ContentRecycleBin = "01BB7FF2-24DC-4C0C-95A2-C24EF72BBAC8";
/// <summary>
/// Guid for the Content Recycle Bin.
/// </summary>
public const string ContentRecycleBin = "01BB7FF2-24DC-4C0C-95A2-C24EF72BBAC8";
/// <summary>
/// Guid for a DataType object.
/// </summary>
public const string DataType = "30A2A501-1978-4DDB-A57B-F7EFED43BA3C";
/// <summary>
/// Guid for a DataType object.
/// </summary>
public const string DataType = "30A2A501-1978-4DDB-A57B-F7EFED43BA3C";
/// <summary>
/// Guid for a Document object.
/// </summary>
public const string Document = "C66BA18E-EAF3-4CFF-8A22-41B16D66A972";
/// <summary>
/// Guid for a Document object.
/// </summary>
public const string Document = "C66BA18E-EAF3-4CFF-8A22-41B16D66A972";
/// <summary>
/// Guid for a Document Type object.
/// </summary>
public const string DocumentType = "A2CB7800-F571-4787-9638-BC48539A0EFB";
/// <summary>
/// Guid for a Document Type object.
/// </summary>
public const string DocumentType = "A2CB7800-F571-4787-9638-BC48539A0EFB";
/// <summary>
/// Guid for a Media object.
/// </summary>
public const string Media = "B796F64C-1F99-4FFB-B886-4BF4BC011A9C";
/// <summary>
/// Guid for a Media object.
/// </summary>
public const string Media = "B796F64C-1F99-4FFB-B886-4BF4BC011A9C";
/// <summary>
/// Guid for the Media Recycle Bin.
/// </summary>
public const string MediaRecycleBin = "CF3D8E34-1C1C-41e9-AE56-878B57B32113";
/// <summary>
/// Guid for the Media Recycle Bin.
/// </summary>
public const string MediaRecycleBin = "CF3D8E34-1C1C-41e9-AE56-878B57B32113";
/// <summary>
/// Guid for a Media Type object.
/// </summary>
public const string MediaType = "4EA4382B-2F5A-4C2B-9587-AE9B3CF3602E";
/// <summary>
/// Guid for a Media Type object.
/// </summary>
public const string MediaType = "4EA4382B-2F5A-4C2B-9587-AE9B3CF3602E";
/// <summary>
/// Guid for a Member object.
/// </summary>
public const string Member = "39EB0F98-B348-42A1-8662-E7EB18487560";
/// <summary>
/// Guid for a Member object.
/// </summary>
public const string Member = "39EB0F98-B348-42A1-8662-E7EB18487560";
/// <summary>
/// Guid for a Member Group object.
/// </summary>
public const string MemberGroup = "366E63B9-880F-4E13-A61C-98069B029728";
/// <summary>
/// Guid for a Member Group object.
/// </summary>
public const string MemberGroup = "366E63B9-880F-4E13-A61C-98069B029728";
/// <summary>
/// Guid for a Member Type object.
/// </summary>
public const string MemberType = "9B5416FB-E72F-45A9-A07B-5A9A2709CE43";
/// <summary>
/// Guid for a Member Type object.
/// </summary>
public const string MemberType = "9B5416FB-E72F-45A9-A07B-5A9A2709CE43";
/// <summary>
/// Guid for a Stylesheet object.
/// </summary>
/// <summary>
/// Guid for a Stylesheet object.
/// </summary>
[Obsolete("This no longer exists in the database")]
public const string Stylesheet = "9F68DA4F-A3A8-44C2-8226-DCBD125E4840";
[Obsolete("This no longer exists in the database")]
internal const string StylesheetProperty = "5555da4f-a123-42b2-4488-dcdfb25e4111";
/// <summary>
/// Guid for the System Root.
/// </summary>
public const string SystemRoot = "EA7D8624-4CFE-4578-A871-24AA946BF34D";
/// <summary>
/// Guid for the System Root.
/// </summary>
public const string SystemRoot = "EA7D8624-4CFE-4578-A871-24AA946BF34D";
/// <summary>
/// Guid for a Template object.
/// </summary>
public const string Template = "6FBDE604-4178-42CE-A10B-8A2600A2F07D";
}
}
/// <summary>
/// Guid for a Template object.
/// </summary>
public const string Template = "6FBDE604-4178-42CE-A10B-8A2600A2F07D";
/// <summary>
/// Guid for a Lock object.
/// </summary>
public const string LockObject = "87A9F1FF-B1E4-4A25-BABB-465A4A47EC41";
}
}
}
+2
View File
@@ -26,6 +26,8 @@
public const int DefaultMediaListViewDataTypeId = -96;
public const int DefaultMembersListViewDataTypeId = -97;
// identifiers for lock objects
public const int ServersLock = -331;
}
}
}
+33 -15
View File
@@ -152,12 +152,7 @@ namespace Umbraco.Core.IO
/// <returns>A value indicating whether the filepath is valid.</returns>
internal static bool VerifyEditPath(string filePath, string validDir)
{
if (filePath.StartsWith(MapPath(SystemDirectories.Root)) == false)
filePath = MapPath(filePath);
if (validDir.StartsWith(MapPath(SystemDirectories.Root)) == false)
validDir = MapPath(validDir);
return filePath.StartsWith(validDir);
return VerifyEditPath(filePath, new[] { validDir });
}
/// <summary>
@@ -182,15 +177,31 @@ namespace Umbraco.Core.IO
/// <returns>A value indicating whether the filepath is valid.</returns>
internal static bool VerifyEditPath(string filePath, IEnumerable<string> validDirs)
{
// this is called from ScriptRepository, PartialViewRepository, etc.
// filePath is the fullPath (rooted, filesystem path, can be trusted)
// validDirs are virtual paths (eg ~/Views)
//
// except that for templates, filePath actually is a virtual path
//TODO
// what's below is dirty, there are too many ways to get the root dir, etc.
// not going to fix everything today
var mappedRoot = MapPath(SystemDirectories.Root);
if (filePath.StartsWith(mappedRoot) == false)
filePath = MapPath(filePath);
// yes we can (see above)
//// don't trust what we get, it may contain relative segments
//filePath = Path.GetFullPath(filePath);
foreach (var dir in validDirs)
{
var validDir = dir;
if (filePath.StartsWith(MapPath(SystemDirectories.Root)) == false)
filePath = MapPath(filePath);
if (validDir.StartsWith(MapPath(SystemDirectories.Root)) == false)
if (validDir.StartsWith(mappedRoot) == false)
validDir = MapPath(validDir);
if (filePath.StartsWith(validDir))
if (PathStartsWith(filePath, validDir, Path.DirectorySeparatorChar))
return true;
}
@@ -219,11 +230,8 @@ namespace Umbraco.Core.IO
/// <returns>A value indicating whether the filepath is valid.</returns>
internal static bool VerifyFileExtension(string filePath, List<string> validFileExtensions)
{
if (filePath.StartsWith(MapPath(SystemDirectories.Root)) == false)
filePath = MapPath(filePath);
var f = new FileInfo(filePath);
return validFileExtensions.Contains(f.Extension.Substring(1));
var ext = Path.GetExtension(filePath);
return ext != null && validFileExtensions.Contains(ext.TrimStart('.'));
}
/// <summary>
@@ -240,6 +248,16 @@ namespace Umbraco.Core.IO
return true;
}
public static bool PathStartsWith(string path, string root, char separator)
{
// either it is identical to root,
// or it is root + separator + anything
if (path.StartsWith(root, StringComparison.OrdinalIgnoreCase) == false) return false;
if (path.Length == root.Length) return true;
if (path.Length < root.Length) return false;
return path[root.Length] == separator;
}
/// <summary>
/// Returns the path to the root of the application, by getting the path to where the assembly where this
+124 -44
View File
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.IO;
using System.Linq;
using Umbraco.Core.Logging;
@@ -9,7 +8,12 @@ namespace Umbraco.Core.IO
{
public class PhysicalFileSystem : IFileSystem
{
internal string RootPath { get; private set; }
// the rooted, filesystem path, using directory separator chars, NOT ending with a separator
// eg "c:" or "c:\path\to\site" or "\\server\path"
private readonly string _rootPath;
// the ??? url, using url separator chars, NOT ending with a separator
// eg "" (?) or "/Scripts" or ???
private readonly string _rootUrl;
public PhysicalFileSystem(string virtualRoot)
@@ -18,8 +22,13 @@ namespace Umbraco.Core.IO
if (virtualRoot.StartsWith("~/") == false)
throw new ArgumentException("The virtualRoot argument must be a virtual path and start with '~/'");
RootPath = IOHelper.MapPath(virtualRoot);
_rootPath = IOHelper.MapPath(virtualRoot);
_rootPath = EnsureDirectorySeparatorChar(_rootPath);
_rootPath = _rootPath.TrimEnd(Path.DirectorySeparatorChar);
_rootUrl = IOHelper.ResolveUrl(virtualRoot);
_rootUrl = EnsureUrlSeparatorChar(_rootUrl);
_rootUrl = _rootUrl.TrimEnd('/');
}
public PhysicalFileSystem(string rootPath, string rootUrl)
@@ -33,18 +42,31 @@ namespace Umbraco.Core.IO
if (rootPath.StartsWith("~/"))
throw new ArgumentException("The rootPath argument cannot be a virtual path and cannot start with '~/'");
RootPath = rootPath;
_rootUrl = rootUrl;
// rootPath should be... rooted, as in, it's a root path!
// but the test suite App.config cannot really "root" anything so we'll have to do it here
//var localRoot = AppDomain.CurrentDomain.BaseDirectory;
var localRoot = IOHelper.GetRootDirectorySafe();
if (Path.IsPathRooted(rootPath) == false)
{
rootPath = Path.Combine(localRoot, rootPath);
}
rootPath = EnsureDirectorySeparatorChar(rootPath);
rootUrl = EnsureUrlSeparatorChar(rootUrl);
_rootPath = rootPath.TrimEnd(Path.DirectorySeparatorChar);
_rootUrl = rootUrl.TrimEnd('/');
}
public IEnumerable<string> GetDirectories(string path)
{
path = EnsureTrailingSeparator(GetFullPath(path));
var fullPath = GetFullPath(path);
try
{
if (Directory.Exists(path))
return Directory.EnumerateDirectories(path).Select(GetRelativePath);
if (Directory.Exists(fullPath))
return Directory.EnumerateDirectories(fullPath).Select(GetRelativePath);
}
catch (UnauthorizedAccessException ex)
{
@@ -65,12 +87,13 @@ namespace Umbraco.Core.IO
public void DeleteDirectory(string path, bool recursive)
{
if (DirectoryExists(path) == false)
var fullPath = GetFullPath(path);
if (Directory.Exists(fullPath) == false)
return;
try
{
Directory.Delete(GetFullPath(path), recursive);
Directory.Delete(fullPath, recursive);
}
catch (DirectoryNotFoundException ex)
{
@@ -80,7 +103,8 @@ namespace Umbraco.Core.IO
public bool DirectoryExists(string path)
{
return Directory.Exists(GetFullPath(path));
var fullPath = GetFullPath(path);
return Directory.Exists(fullPath);
}
public void AddFile(string path, Stream stream)
@@ -90,17 +114,17 @@ namespace Umbraco.Core.IO
public void AddFile(string path, Stream stream, bool overrideIfExists)
{
var fsRelativePath = GetRelativePath(path);
var fullPath = GetFullPath(path);
var exists = File.Exists(fullPath);
if (exists && overrideIfExists == false)
throw new InvalidOperationException(string.Format("A file at path '{0}' already exists", path));
var exists = FileExists(fsRelativePath);
if (exists && overrideIfExists == false) throw new InvalidOperationException(string.Format("A file at path '{0}' already exists", path));
EnsureDirectory(Path.GetDirectoryName(fsRelativePath));
Directory.CreateDirectory(Path.GetDirectoryName(fullPath)); // ensure it exists
if (stream.CanSeek)
stream.Seek(0, 0);
using (var destination = (Stream)File.Create(GetFullPath(fsRelativePath)))
using (var destination = (Stream)File.Create(fullPath))
stream.CopyTo(destination);
}
@@ -111,9 +135,7 @@ namespace Umbraco.Core.IO
public IEnumerable<string> GetFiles(string path, string filter)
{
var fsRelativePath = GetRelativePath(path);
var fullPath = EnsureTrailingSeparator(GetFullPath(fsRelativePath));
var fullPath = GetFullPath(path);
try
{
@@ -140,12 +162,13 @@ namespace Umbraco.Core.IO
public void DeleteFile(string path)
{
if (!FileExists(path))
var fullPath = GetFullPath(path);
if (File.Exists(fullPath) == false)
return;
try
{
File.Delete(GetFullPath(path));
File.Delete(fullPath);
}
catch (FileNotFoundException ex)
{
@@ -155,39 +178,86 @@ namespace Umbraco.Core.IO
public bool FileExists(string path)
{
return File.Exists(GetFullPath(path));
var fullpath = GetFullPath(path);
return File.Exists(fullpath);
}
// beware, many things depend on how the GetRelative/AbsolutePath methods work!
/// <summary>
/// Gets the relative path.
/// </summary>
/// <param name="fullPathOrUrl">The full path or url.</param>
/// <returns>The path, relative to this filesystem's root.</returns>
/// <remarks>
/// <para>The relative path is relative to this filesystem's root, not starting with any
/// directory separator. If input was recognized as a url (path), then output uses url (path) separator
/// chars.</para>
/// </remarks>
public string GetRelativePath(string fullPathOrUrl)
{
var relativePath = fullPathOrUrl
.TrimStart(_rootUrl)
.Replace('/', Path.DirectorySeparatorChar)
.TrimStart(RootPath)
.TrimStart(Path.DirectorySeparatorChar);
// test url
var path = fullPathOrUrl.Replace('\\', '/'); // ensure url separator char
return relativePath;
if (IOHelper.PathStartsWith(path, _rootUrl, '/')) // if it starts with the root url...
return path.Substring(_rootUrl.Length) // strip it
.TrimStart('/'); // it's relative
// test path
path = EnsureDirectorySeparatorChar(fullPathOrUrl);
if (IOHelper.PathStartsWith(path, _rootPath, Path.DirectorySeparatorChar)) // if it starts with the root path
return path.Substring(_rootPath.Length) // strip it
.TrimStart(Path.DirectorySeparatorChar); // it's relative
// unchanged - including separators
return fullPathOrUrl;
}
/// <summary>
/// Gets the full path.
/// </summary>
/// <param name="path">The full or relative path.</param>
/// <returns>The full path.</returns>
/// <remarks>
/// <para>On the physical filesystem, the full path is the rooted (ie non-relative), safe (ie within this
/// filesystem's root) path. All separators are converted to Path.DirectorySeparatorChar.</para>
/// </remarks>
public string GetFullPath(string path)
{
//if the path starts with a '/' then it's most likely not a FS relative path which is required so convert it
if (path.StartsWith("/"))
{
path = GetRelativePath(path);
}
// normalize
var opath = path;
path = EnsureDirectorySeparatorChar(path);
return !path.StartsWith(RootPath)
? Path.Combine(RootPath, path)
: path;
// not sure what we are doing here - so if input starts with a (back) slash,
// we assume it's not a FS relative path and we try to convert it... but it
// really makes little sense?
if (path.StartsWith(Path.DirectorySeparatorChar.ToString()))
path = GetRelativePath(path);
// if already a full path, return
if (IOHelper.PathStartsWith(path, _rootPath, Path.DirectorySeparatorChar))
return path;
// else combine and sanitize, ie GetFullPath will take care of any relative
// segments in path, eg '../../foo.tmp' - it may throw a SecurityException
// if the combined path reaches illegal parts of the filesystem
var fpath = Path.Combine(_rootPath, path);
fpath = Path.GetFullPath(fpath);
// at that point, path is within legal parts of the filesystem, ie we have
// permissions to reach that path, but it may nevertheless be outside of
// our root path, due to relative segments, so better check
if (IOHelper.PathStartsWith(fpath, _rootPath, Path.DirectorySeparatorChar))
return fpath;
throw new FileSecurityException("File '" + opath + "' is outside this filesystem's root.");
}
public string GetUrl(string path)
{
return _rootUrl.TrimEnd("/") + "/" + path
.TrimStart(Path.DirectorySeparatorChar)
.Replace(Path.DirectorySeparatorChar, '/')
.TrimEnd("/");
path = EnsureUrlSeparatorChar(path).Trim('/');
return _rootUrl + "/" + path;
}
public DateTimeOffset GetLastModified(string path)
@@ -214,9 +284,19 @@ namespace Umbraco.Core.IO
protected string EnsureTrailingSeparator(string path)
{
if (!path.EndsWith(Path.DirectorySeparatorChar.ToString(CultureInfo.InvariantCulture), StringComparison.Ordinal))
path = path + Path.DirectorySeparatorChar;
return path.EnsureEndsWith(Path.DirectorySeparatorChar);
}
protected string EnsureDirectorySeparatorChar(string path)
{
path = path.Replace('/', Path.DirectorySeparatorChar);
path = path.Replace('\\', Path.DirectorySeparatorChar);
return path;
}
protected string EnsureUrlSeparatorChar(string path)
{
path = path.Replace('\\', '/');
return path;
}
+57 -13
View File
@@ -2,6 +2,8 @@
using System.IO;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text;
using Umbraco.Core.IO;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Models
@@ -15,12 +17,20 @@ namespace Umbraco.Core.Models
{
private string _path;
private string _originalPath;
private string _content = string.Empty; //initialize to empty string, not null
protected File(string path)
// initialize to string.Empty so that it is possible to save a new file,
// should use the lazyContent ctor to set it to null when loading existing.
// cannot simply use HasIdentity as some classes (eg Script) override it
// in a weird way.
private string _content;
internal Func<File, string> GetFileContent { get; set; }
protected File(string path, Func<File, string> getFileContent = null)
{
_path = path;
_path = SanitizePath(path);
_originalPath = _path;
GetFileContent = getFileContent;
_content = getFileContent != null ? null : string.Empty;
}
private static readonly PropertyInfo ContentSelector = ExpressionHelper.GetPropertyInfo<File, string>(x => x.Content);
@@ -28,6 +38,14 @@ namespace Umbraco.Core.Models
private string _alias;
private string _name;
private static string SanitizePath(string path)
{
return path
.Replace('\\', System.IO.Path.DirectorySeparatorChar)
.Replace('/', System.IO.Path.DirectorySeparatorChar);
//.TrimStart(System.IO.Path.DirectorySeparatorChar);
}
/// <summary>
/// Gets or sets the Name of the File including extension
/// </summary>
@@ -71,7 +89,7 @@ namespace Umbraco.Core.Models
SetPropertyValueAndDetectChanges(o =>
{
_path = value;
_path = SanitizePath(value);
return _path;
}, _path, PathSelector);
}
@@ -96,15 +114,26 @@ namespace Umbraco.Core.Models
/// <summary>
/// Gets or sets the Content of a File
/// </summary>
/// <remarks>Marked as DoNotClone, because it should be lazy-reloaded from disk.</remarks>
[DataMember]
[DoNotClone]
public virtual string Content
{
get { return _content; }
get
{
if (_content != null)
return _content;
// else, must lazy-load, and ensure it's not null
if (GetFileContent != null)
_content = GetFileContent(this);
return _content ?? (_content = string.Empty);
}
set
{
SetPropertyValueAndDetectChanges(o =>
{
_content = value;
_content = value ?? string.Empty; // cannot set to null
return _content;
}, _content, ContentSelector);
}
@@ -121,17 +150,32 @@ namespace Umbraco.Core.Models
return true;
}
// this exists so that class that manage name and alias differently, eg Template,
// can implement their own cloning - (though really, not sure it's even needed)
protected virtual void DeepCloneNameAndAlias(File clone)
{
// set fields that have a lazy value, by forcing evaluation of the lazy
clone._name = Name;
clone._alias = Alias;
}
public override object DeepClone()
{
var clone = (File)base.DeepClone();
//turn off change tracking
var clone = (File) base.DeepClone();
// clear fields that were memberwise-cloned and that we don't want to clone
clone._content = null;
// turn off change tracking
clone.DisableChangeTracking();
//need to manually assign since they are readonly properties
clone._alias = Alias;
clone._name = Name;
//this shouldn't really be needed since we're not tracking
// ...
DeepCloneNameAndAlias(clone);
// this shouldn't really be needed since we're not tracking
clone.ResetDirtyProperties(false);
//re-enable tracking
// re-enable tracking
clone.EnableChangeTracking();
return clone;
@@ -0,0 +1,14 @@
using System;
namespace Umbraco.Core.Models
{
/// <summary>
/// Represents a cached content with a GUID key.
/// </summary>
/// <remarks>This is temporary, because we cannot add the Key property to IPublishedContent without
/// breaking backward compatibility. With v8, it will be merged into IPublishedContent.</remarks>
public interface IPublishedContentWithKey : IPublishedContent
{
Guid Key { get; }
}
}
@@ -18,6 +18,11 @@ namespace Umbraco.Core.Models
/// </summary>
bool IsActive { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the server is master.
/// </summary>
bool IsMaster { get; set; }
/// <summary>
/// Gets the date and time the registration was created.
/// </summary>
+8 -9
View File
@@ -1,9 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text.RegularExpressions;
using Umbraco.Core.IO;
using Umbraco.Core.Services;
namespace Umbraco.Core.Models
{
@@ -15,12 +12,14 @@ namespace Umbraco.Core.Models
[DataContract(IsReference = true)]
public class PartialView : File, IPartialView
{
public PartialView(string path)
: base(path)
{
base.Path = path;
}
: this(path, null)
{ }
internal PartialView(string path, Func<File, string> getFileContent)
: base(path, getFileContent)
{ }
internal PartialViewType ViewType { get; set; }
}
}
@@ -0,0 +1,9 @@
namespace Umbraco.Core.Models
{
internal enum PartialViewType : byte
{
Unknown = 0, // default
PartialView = 1,
PartialViewMacro = 2
}
}
@@ -62,9 +62,20 @@ namespace Umbraco.Core.Models.PublishedContent
// model and therefore returned the original content unchanged.
var model = content.CreateModel();
var extended = model == content // == means the factory did not create a model
? new PublishedContentExtended(content) // so we have to extend
: model; // else we can use what the factory returned
IPublishedContent extended;
if (model == content) // == means the factory did not create a model
{
// so we have to extend
var contentWithKey = content as IPublishedContentWithKey;
extended = contentWithKey == null
? new PublishedContentExtended(content)
: new PublishedContentWithKeyExtended(contentWithKey);
}
else
{
// else we can use what the factory returned
extended = model;
}
// so extended should always implement IPublishedContentExtended, however if
// by mistake the factory returned a different object that does not implement
@@ -0,0 +1,14 @@
using System;
namespace Umbraco.Core.Models.PublishedContent
{
public class PublishedContentWithKeyExtended : PublishedContentExtended, IPublishedContentWithKey
{
// protected for models, internal for PublishedContentExtended static Extend method
protected internal PublishedContentWithKeyExtended(IPublishedContentWithKey content)
: base(content)
{ }
public Guid Key { get { return ((IPublishedContentWithKey) Content).Key; } }
}
}
@@ -0,0 +1,13 @@
using System;
namespace Umbraco.Core.Models.PublishedContent
{
public abstract class PublishedContentWithKeyModel : PublishedContentModel, IPublishedContentWithKey
{
protected PublishedContentWithKeyModel(IPublishedContentWithKey content)
: base (content)
{ }
public Guid Key { get { return ((IPublishedContentWithKey) Content).Key; } }
}
}
@@ -0,0 +1,17 @@
using System;
namespace Umbraco.Core.Models.PublishedContent
{
/// <summary>
/// Provides an abstract base class for <c>IPublishedContentWithKey</c> implementations that
/// wrap and extend another <c>IPublishedContentWithKey</c>.
/// </summary>
public class PublishedContentWithKeyWrapped : PublishedContentWrapped, IPublishedContentWithKey
{
protected PublishedContentWithKeyWrapped(IPublishedContentWithKey content)
: base(content)
{ }
public virtual Guid Key { get { return ((IPublishedContentWithKey) Content).Key; } }
}
}
+3 -2
View File
@@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.Security.AccessControl;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.DatabaseAnnotations;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
namespace Umbraco.Core.Models.Rdbms
{
@@ -30,11 +31,11 @@ namespace Umbraco.Core.Models.Rdbms
public int NoAccessNodeId { get; set; }
[Column("createDate")]
[Constraint(Default = "getdate()")]
[Constraint(Default = SystemMethods.CurrentDateTime)]
public DateTime CreateDate { get; set; }
[Column("updateDate")]
[Constraint(Default = "getdate()")]
[Constraint(Default = SystemMethods.CurrentDateTime)]
public DateTime UpdateDate { get; set; }
[ResultColumn]
@@ -1,6 +1,7 @@
using System;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.DatabaseAnnotations;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
namespace Umbraco.Core.Models.Rdbms
{
@@ -25,11 +26,11 @@ namespace Umbraco.Core.Models.Rdbms
public string RuleType { get; set; }
[Column("createDate")]
[Constraint(Default = "getdate()")]
[Constraint(Default = SystemMethods.CurrentDateTime)]
public DateTime CreateDate { get; set; }
[Column("updateDate")]
[Constraint(Default = "getdate()")]
[Constraint(Default = SystemMethods.CurrentDateTime)]
public DateTime UpdateDate { get; set; }
}
}
@@ -1,6 +1,7 @@
using System;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.DatabaseAnnotations;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
namespace Umbraco.Core.Models.Rdbms
{
@@ -23,7 +24,7 @@ namespace Umbraco.Core.Models.Rdbms
public Guid VersionId { get; set; }
[Column("VersionDate")]
[Constraint(Default = "getdate()")]
[Constraint(Default = SystemMethods.CurrentDateTime)]
public DateTime VersionDate { get; set; }
[ResultColumn]
+2 -1
View File
@@ -1,6 +1,7 @@
using System;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.DatabaseAnnotations;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
namespace Umbraco.Core.Models.Rdbms
{
@@ -38,7 +39,7 @@ namespace Umbraco.Core.Models.Rdbms
public DateTime? ExpiresDate { get; set; }
[Column("updateDate")]
[Constraint(Default = "getdate()")]
[Constraint(Default = SystemMethods.CurrentDateTime)]
public DateTime UpdateDate { get; set; }
[Column("templateId")]
@@ -1,6 +1,7 @@
using System;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.DatabaseAnnotations;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
namespace Umbraco.Core.Models.Rdbms
{
@@ -27,7 +28,7 @@ namespace Umbraco.Core.Models.Rdbms
public string ProviderKey { get; set; }
[Column("createDate")]
[Constraint(Default = "getdate()")]
[Constraint(Default = SystemMethods.CurrentDateTime)]
public DateTime CreateDate { get; set; }
+2 -1
View File
@@ -1,6 +1,7 @@
using System;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.DatabaseAnnotations;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
namespace Umbraco.Core.Models.Rdbms
{
@@ -21,7 +22,7 @@ namespace Umbraco.Core.Models.Rdbms
public int NodeId { get; set; }
[Column("Datestamp")]
[Constraint(Default = "getdate()")]
[Constraint(Default = SystemMethods.CurrentDateTime)]
public DateTime Datestamp { get; set; }
[Column("logHeader")]
@@ -1,6 +1,7 @@
using System;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.DatabaseAnnotations;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
namespace Umbraco.Core.Models.Rdbms
{
@@ -19,7 +20,7 @@ namespace Umbraco.Core.Models.Rdbms
public string Name { get; set; }
[Column("createDate")]
[Constraint(Default = "getdate()")]
[Constraint(Default = SystemMethods.CurrentDateTime)]
public DateTime CreateDate { get; set; }
[Column("version")]
+3 -2
View File
@@ -1,6 +1,7 @@
using System;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.DatabaseAnnotations;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
namespace Umbraco.Core.Models.Rdbms
{
@@ -48,7 +49,7 @@ namespace Umbraco.Core.Models.Rdbms
[Column("uniqueID")]
[NullSetting(NullSetting = NullSettings.NotNull)]
[Index(IndexTypes.UniqueNonClustered, Name = "IX_umbracoNodeUniqueID")]
[Constraint(Default = "newid()")]
[Constraint(Default = SystemMethods.NewGuid)]
public Guid UniqueId { get; set; }
[Column("text")]
@@ -61,7 +62,7 @@ namespace Umbraco.Core.Models.Rdbms
public Guid? NodeObjectType { get; set; }
[Column("createDate")]
[Constraint(Default = "getdate()")]
[Constraint(Default = SystemMethods.CurrentDateTime)]
public DateTime CreateDate { get; set; }
}
}
@@ -1,6 +1,7 @@
using System;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.DatabaseAnnotations;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
namespace Umbraco.Core.Models.Rdbms
{
@@ -61,7 +62,7 @@ namespace Umbraco.Core.Models.Rdbms
[Column("UniqueID")]
[NullSetting(NullSetting = NullSettings.NotNull)]
[Constraint(Default = "newid()")]
[Constraint(Default = SystemMethods.NewGuid)]
[Index(IndexTypes.UniqueNonClustered, Name = "IX_cmsPropertyTypeUniqueID")]
public Guid UniqueId { get; set; }
}
+2 -1
View File
@@ -1,6 +1,7 @@
using System;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.DatabaseAnnotations;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
namespace Umbraco.Core.Models.Rdbms
{
@@ -26,7 +27,7 @@ namespace Umbraco.Core.Models.Rdbms
public int RelationType { get; set; }
[Column("datetime")]
[Constraint(Default = "getdate()")]
[Constraint(Default = SystemMethods.CurrentDateTime)]
public DateTime Datetime { get; set; }
[Column("comment")]
@@ -1,6 +1,7 @@
using System;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.DatabaseAnnotations;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
namespace Umbraco.Core.Models.Rdbms
{
@@ -23,7 +24,7 @@ namespace Umbraco.Core.Models.Rdbms
public string ServerIdentity { get; set; }
[Column("registeredDate")]
[Constraint(Default = "getdate()")]
[Constraint(Default = SystemMethods.CurrentDateTime)]
public DateTime DateRegistered { get; set; }
[Column("lastNotifiedDate")]
@@ -33,6 +34,7 @@ namespace Umbraco.Core.Models.Rdbms
[Index(IndexTypes.NonClustered)]
public bool IsActive { get; set; }
[Column("isMaster")]
public bool IsMaster { get; set; }
}
}
+2 -1
View File
@@ -1,6 +1,7 @@
using System;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.DatabaseAnnotations;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
namespace Umbraco.Core.Models.Rdbms
{
@@ -34,7 +35,7 @@ namespace Umbraco.Core.Models.Rdbms
public int UserId { get; set; }
[Column("DateTime")]
[Constraint(Default = "getdate()")]
[Constraint(Default = SystemMethods.CurrentDateTime)]
public DateTime DateTime { get; set; }
[Column("Comment")]
+8 -9
View File
@@ -1,7 +1,5 @@
using System;
using System.Linq;
using System.Runtime.Serialization;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.IO;
@@ -15,16 +13,17 @@ namespace Umbraco.Core.Models
public class Script : File
{
public Script(string path)
: base(path)
{
}
: this(path, (Func<File, string>) null)
{ }
internal Script(string path, Func<File, string> getFileContent)
: base(path, getFileContent)
{ }
[Obsolete("This is no longer used and will be removed from the codebase in future versions")]
public Script(string path, IContentSection contentConfig)
: this(path)
{
}
: base(path)
{ }
/// <summary>
/// Indicates whether the current entity has an identity, which in this case is a path/name.
+22 -3
View File
@@ -2,7 +2,6 @@
using System.Globalization;
using System.Reflection;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Sync;
namespace Umbraco.Core.Models
{
@@ -14,10 +13,12 @@ namespace Umbraco.Core.Models
private string _serverAddress;
private string _serverIdentity;
private bool _isActive;
private bool _isMaster;
private static readonly PropertyInfo ServerAddressSelector = ExpressionHelper.GetPropertyInfo<ServerRegistration, string>(x => x.ServerAddress);
private static readonly PropertyInfo ServerIdentitySelector = ExpressionHelper.GetPropertyInfo<ServerRegistration, string>(x => x.ServerIdentity);
private static readonly PropertyInfo IsActiveSelector = ExpressionHelper.GetPropertyInfo<ServerRegistration, bool>(x => x.IsActive);
private static readonly PropertyInfo IsMasterSelector = ExpressionHelper.GetPropertyInfo<ServerRegistration, bool>(x => x.IsMaster);
/// <summary>
/// Initialiazes a new instance of the <see cref="ServerRegistration"/> class.
@@ -34,7 +35,8 @@ namespace Umbraco.Core.Models
/// <param name="registered">The date and time the registration was created.</param>
/// <param name="accessed">The date and time the registration was last accessed.</param>
/// <param name="isActive">A value indicating whether the registration is active.</param>
public ServerRegistration(int id, string serverAddress, string serverIdentity, DateTime registered, DateTime accessed, bool isActive)
/// <param name="isMaster">A value indicating whether the registration is master.</param>
public ServerRegistration(int id, string serverAddress, string serverIdentity, DateTime registered, DateTime accessed, bool isActive, bool isMaster)
{
UpdateDate = accessed;
CreateDate = registered;
@@ -43,6 +45,7 @@ namespace Umbraco.Core.Models
ServerAddress = serverAddress;
ServerIdentity = serverIdentity;
IsActive = isActive;
IsMaster = isMaster;
}
/// <summary>
@@ -108,6 +111,22 @@ namespace Umbraco.Core.Models
}
}
/// <summary>
/// Gets or sets a value indicating whether the server is master.
/// </summary>
public bool IsMaster
{
get { return _isMaster; }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_isMaster = value;
return _isMaster;
}, _isMaster, IsMasterSelector);
}
}
/// <summary>
/// Gets the date and time the registration was created.
/// </summary>
@@ -124,7 +143,7 @@ namespace Umbraco.Core.Models
/// <returns></returns>
public override string ToString()
{
return string.Format("{{\"{0}\", \"{1}\", {2}active}}", ServerAddress, ServerIdentity, IsActive ? "" : "!");
return string.Format("{{\"{0}\", \"{1}\", {2}active, {3}master}}", ServerAddress, ServerIdentity, IsActive ? "" : "!", IsMaster ? "" : "!");
}
}
}
+10 -6
View File
@@ -1,9 +1,9 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using Umbraco.Core.IO;
using Umbraco.Core.Strings.Css;
@@ -16,12 +16,16 @@ namespace Umbraco.Core.Models
[DataContract(IsReference = true)]
public class Stylesheet : File
{
public Stylesheet(string path)
: base(path.EnsureEndsWith(".css"))
{
public Stylesheet(string path)
: this(path, null)
{ }
internal Stylesheet(string path, Func<File, string> getFileContent)
: base(path.EnsureEndsWith(".css"), getFileContent)
{
InitializeProperties();
}
private Lazy<List<StylesheetProperty>> _properties;
private void InitializeProperties()
@@ -81,7 +85,7 @@ namespace Umbraco.Core.Models
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void Property_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
void Property_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
var prop = (StylesheetProperty) sender;
+11 -23
View File
@@ -1,7 +1,10 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.IO;
@@ -29,12 +32,16 @@ namespace Umbraco.Core.Models
private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<Template, string>(x => x.Name);
public Template(string name, string alias)
: base(string.Empty)
: this(name, alias, (Func<File, string>) null)
{ }
internal Template(string name, string alias, Func<File, string> getFileContent)
: base(string.Empty, getFileContent)
{
_name = name;
_alias = alias.ToCleanString(CleanStringType.UnderscoreAlias);
_masterTemplateId = new Lazy<int>(() => -1);
}
}
[Obsolete("This constructor should not be used, file path is determined by alias, setting the path here will have no affect")]
public Template(string path, string name, string alias)
@@ -123,7 +130,6 @@ namespace Umbraco.Core.Models
Key = Guid.NewGuid();
}
public void SetMasterTemplate(ITemplate masterTemplate)
{
if (masterTemplate == null)
@@ -139,27 +145,9 @@ namespace Umbraco.Core.Models
}
public override object DeepClone()
protected override void DeepCloneNameAndAlias(File clone)
{
//We cannot call in to the base classes to clone because the base File class treats Alias, Name.. differently so we need to manually do the clone
//Memberwise clone on Entity will work since it doesn't have any deep elements
// for any sub class this will work for standard properties as well that aren't complex object's themselves.
var clone = (Template)MemberwiseClone();
//turn off change tracking
clone.DisableChangeTracking();
//Automatically deep clone ref properties that are IDeepCloneable
DeepCloneHelper.DeepCloneRefProperties(this, clone);
//this shouldn't really be needed since we're not tracking
clone.ResetDirtyProperties(false);
//re-enable tracking
clone.EnableChangeTracking();
return clone;
// do nothing - prevents File from doing its stuff
}
}
}
@@ -20,6 +20,6 @@ namespace Umbraco.Core.Persistence.DatabaseAnnotations
/// <summary>
/// Gets or sets the Default value
/// </summary>
public string Default { get; set; }
public object Default { get; set; }
}
}
@@ -3,8 +3,8 @@ namespace Umbraco.Core.Persistence.DatabaseModelDefinitions
public enum SystemMethods
{
NewGuid,
NewSequentialId,
CurrentDateTime,
CurrentUTCDateTime
//NewSequentialId,
//CurrentUTCDateTime
}
}
@@ -80,9 +80,6 @@ namespace Umbraco.Core.Persistence
var creation = new DatabaseSchemaCreation(_db, _logger, _syntaxProvider);
creation.InitializeDatabaseSchema();
//Now ensure to cretae the tag in the db for the current migration version
migrationEntryService.CreateEntry(GlobalSettings.UmbracoMigrationName, UmbracoVersion.GetSemanticVersion());
_logger.Info<Database>("Finalized database schema creation");
}
@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Runtime.CompilerServices;
namespace Umbraco.Core.Persistence
{
internal static class DatabaseNodeLockExtensions
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void ValidateDatabase(UmbracoDatabase database)
{
if (database == null)
throw new ArgumentNullException("database");
if (database.CurrentTransactionIsolationLevel < IsolationLevel.RepeatableRead)
throw new InvalidOperationException("A transaction with minimum RepeatableRead isolation level is required.");
}
// updating a record within a repeatable-read transaction gets an exclusive lock on
// that record which will be kept until the transaction is ended, effectively locking
// out all other accesses to that record - thus obtaining an exclusive lock over the
// protected resources.
public static void AcquireLockNodeWriteLock(this UmbracoDatabase database, int nodeId)
{
ValidateDatabase(database);
database.Execute("UPDATE umbracoNode SET sortOrder = (CASE WHEN (sortOrder=1) THEN -1 ELSE 1 END) WHERE id=@id",
new { @id = nodeId });
}
// reading a record within a repeatable-read transaction gets a shared lock on
// that record which will be kept until the transaction is ended, effectively preventing
// other write accesses to that record - thus obtaining a shared lock over the protected
// resources.
public static void AcquireLockNodeReadLock(this UmbracoDatabase database, int nodeId)
{
ValidateDatabase(database);
database.ExecuteScalar<int>("SELECT sortOrder FROM umbracoNode WHERE id=@id",
new { @id = nodeId });
}
}
}
@@ -7,7 +7,7 @@ namespace Umbraco.Core.Persistence.Factories
{
public ServerRegistration BuildEntity(ServerRegistrationDto dto)
{
var model = new ServerRegistration(dto.Id, dto.ServerAddress, dto.ServerIdentity, dto.DateRegistered, dto.DateAccessed, dto.IsActive);
var model = new ServerRegistration(dto.Id, dto.ServerAddress, dto.ServerIdentity, dto.DateRegistered, dto.DateAccessed, dto.IsActive, dto.IsMaster);
//on initial construction we don't want to have dirty properties tracked
// http://issues.umbraco.org/issue/U4-1946
model.ResetDirtyProperties(false);
@@ -21,6 +21,7 @@ namespace Umbraco.Core.Persistence.Factories
ServerAddress = entity.ServerAddress,
DateRegistered = entity.CreateDate,
IsActive = entity.IsActive,
IsMaster = ((ServerRegistration) entity).IsMaster,
DateAccessed = entity.UpdateDate,
ServerIdentity = entity.ServerIdentity
};
@@ -33,9 +33,9 @@ namespace Umbraco.Core.Persistence.Factories
#region Implementation of IEntityFactory<ITemplate,TemplateDto>
public Template BuildEntity(TemplateDto dto, IEnumerable<IUmbracoEntity> childDefinitions)
public Template BuildEntity(TemplateDto dto, IEnumerable<IUmbracoEntity> childDefinitions, Func<File, string> getFileContent)
{
var template = new Template(dto.NodeDto.Text, dto.Alias)
var template = new Template(dto.NodeDto.Text, dto.Alias, getFileContent)
{
CreateDate = dto.NodeDto.CreateDate,
Id = dto.NodeId,
@@ -0,0 +1,27 @@
using System;
using Umbraco.Core.Persistence.Repositories;
using Umbraco.Core.Persistence.UnitOfWork;
namespace Umbraco.Core.Persistence
{
internal class LockedRepository<TRepository>
where TRepository : IDisposable, IRepository
{
public LockedRepository(Transaction transaction, IDatabaseUnitOfWork unitOfWork, TRepository repository)
{
Transaction = transaction;
UnitOfWork = unitOfWork;
Repository = repository;
}
public Transaction Transaction { get; private set; }
public IDatabaseUnitOfWork UnitOfWork { get; private set; }
public TRepository Repository { get; private set; }
public void Commit()
{
UnitOfWork.Commit();
Transaction.Complete();
}
}
}
@@ -0,0 +1,103 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using Umbraco.Core.Persistence.Repositories;
using Umbraco.Core.Persistence.UnitOfWork;
namespace Umbraco.Core.Persistence
{
internal class LockingRepository<TRepository>
where TRepository : IDisposable, IRepository
{
private readonly IDatabaseUnitOfWorkProvider _uowProvider;
private readonly Func<IDatabaseUnitOfWork, TRepository> _repositoryFactory;
private readonly int[] _readLockIds, _writeLockIds;
public LockingRepository(IDatabaseUnitOfWorkProvider uowProvider, Func<IDatabaseUnitOfWork, TRepository> repositoryFactory,
IEnumerable<int> readLockIds, IEnumerable<int> writeLockIds)
{
Mandate.ParameterNotNull(uowProvider, "uowProvider");
Mandate.ParameterNotNull(repositoryFactory, "repositoryFactory");
_uowProvider = uowProvider;
_repositoryFactory = repositoryFactory;
_readLockIds = readLockIds == null ? new int[0] : readLockIds.ToArray();
_writeLockIds = writeLockIds == null ? new int[0] : writeLockIds.ToArray();
}
public void WithReadLocked(Action<LockedRepository<TRepository>> action, bool autoCommit = true)
{
var uow = _uowProvider.GetUnitOfWork();
using (var transaction = uow.Database.GetTransaction(IsolationLevel.RepeatableRead))
{
foreach (var lockId in _readLockIds)
uow.Database.AcquireLockNodeReadLock(lockId);
using (var repository = _repositoryFactory(uow))
{
action(new LockedRepository<TRepository>(transaction, uow, repository));
if (autoCommit == false) return;
uow.Commit();
transaction.Complete();
}
}
}
public TResult WithReadLocked<TResult>(Func<LockedRepository<TRepository>, TResult> func, bool autoCommit = true)
{
var uow = _uowProvider.GetUnitOfWork();
using (var transaction = uow.Database.GetTransaction(IsolationLevel.RepeatableRead))
{
foreach (var lockId in _readLockIds)
uow.Database.AcquireLockNodeReadLock(lockId);
using (var repository = _repositoryFactory(uow))
{
var ret = func(new LockedRepository<TRepository>(transaction, uow, repository));
if (autoCommit == false) return ret;
uow.Commit();
transaction.Complete();
return ret;
}
}
}
public void WithWriteLocked(Action<LockedRepository<TRepository>> action, bool autoCommit = true)
{
var uow = _uowProvider.GetUnitOfWork();
using (var transaction = uow.Database.GetTransaction(IsolationLevel.RepeatableRead))
{
foreach (var lockId in _writeLockIds)
uow.Database.AcquireLockNodeWriteLock(lockId);
using (var repository = _repositoryFactory(uow))
{
action(new LockedRepository<TRepository>(transaction, uow, repository));
if (autoCommit == false) return;
uow.Commit();
transaction.Complete();
}
}
}
public TResult WithWriteLocked<TResult>(Func<LockedRepository<TRepository>, TResult> func, bool autoCommit = true)
{
var uow = _uowProvider.GetUnitOfWork();
using (var transaction = uow.Database.GetTransaction(IsolationLevel.RepeatableRead))
{
foreach (var lockId in _writeLockIds)
uow.Database.AcquireLockNodeReadLock(lockId);
using (var repository = _repositoryFactory(uow))
{
var ret = func(new LockedRepository<TRepository>(transaction, uow, repository));
if (autoCommit == false) return ret;
uow.Commit();
transaction.Complete();
return ret;
}
}
}
}
}
@@ -30,6 +30,7 @@ namespace Umbraco.Core.Persistence.Mappers
{
CacheMap<ServerRegistration, ServerRegistrationDto>(src => src.Id, dto => dto.Id);
CacheMap<ServerRegistration, ServerRegistrationDto>(src => src.IsActive, dto => dto.IsActive);
CacheMap<ServerRegistration, ServerRegistrationDto>(src => src.IsMaster, dto => dto.IsMaster);
CacheMap<ServerRegistration, ServerRegistrationDto>(src => src.ServerAddress, dto => dto.ServerAddress);
CacheMap<ServerRegistration, ServerRegistrationDto>(src => src.CreateDate, dto => dto.DateRegistered);
CacheMap<ServerRegistration, ServerRegistrationDto>(src => src.UpdateDate, dto => dto.DateAccessed);
@@ -1,4 +1,5 @@
using System;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Rdbms;
@@ -86,11 +87,17 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
{
CreateUmbracoRelationTypeData();
}
if (tableName.Equals("cmsTaskType"))
{
CreateCmsTaskTypeData();
}
if (tableName.Equals("umbracoMigration"))
{
CreateUmbracoMigrationData();
}
_logger.Info<BaseDataCreation>(string.Format("Done creating data in table {0}", tableName));
}
@@ -274,5 +281,18 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
{
_database.Insert("cmsTaskType", "id", false, new TaskTypeDto { Id = 1, Alias = "toTranslate" });
}
private void CreateUmbracoMigrationData()
{
var dto = new MigrationDto
{
Id = 1,
Name = GlobalSettings.UmbracoMigrationName,
Version = UmbracoVersion.GetSemanticVersion().ToString(),
CreateDate = DateTime.Now
};
_database.Insert("umbracoMigration", "pk", false, dto);
}
}
}
@@ -16,13 +16,7 @@ namespace Umbraco.Core.Persistence.Migrations
{
public ISqlSyntaxProvider SqlSyntax { get; private set; }
public ILogger Logger { get; private set; }
[Obsolete("Use the other constructor specifying all dependencies instead")]
protected MigrationBase()
: this(SqlSyntaxContext.SqlSyntaxProvider, LoggerResolver.Current.Logger)
{
}
protected MigrationBase(ISqlSyntaxProvider sqlSyntax, ILogger logger)
{
SqlSyntax = sqlSyntax;
@@ -48,7 +42,7 @@ namespace Umbraco.Core.Persistence.Migrations
public IAlterSyntaxBuilder Alter
{
get { return new AlterSyntaxBuilder(Context); }
get { return new AlterSyntaxBuilder(Context, SqlSyntax); }
}
public ICreateBuilder Create
@@ -63,27 +57,27 @@ namespace Umbraco.Core.Persistence.Migrations
public IExecuteBuilder Execute
{
get { return new ExecuteBuilder(Context); }
get { return new ExecuteBuilder(Context, SqlSyntax); }
}
public IInsertBuilder Insert
{
get { return new InsertBuilder(Context); }
get { return new InsertBuilder(Context, SqlSyntax); }
}
public IRenameBuilder Rename
{
get { return new RenameBuilder(Context); }
get { return new RenameBuilder(Context, SqlSyntax); }
}
public IUpdateBuilder Update
{
get { return new UpdateBuilder(Context); }
get { return new UpdateBuilder(Context, SqlSyntax); }
}
public IIfDatabaseBuilder IfDatabase(params DatabaseProviders[] databaseProviders)
{
return new IfDatabaseBuilder(Context, databaseProviders);
return new IfDatabaseBuilder(Context, SqlSyntax, databaseProviders);
}
}
}
@@ -7,22 +7,22 @@ namespace Umbraco.Core.Persistence.Migrations
{
public abstract class MigrationExpressionBase : IMigrationExpression
{
[Obsolete("Use the other constructors specifying an ISqlSyntaxProvider instead")]
protected MigrationExpressionBase()
: this(SqlSyntaxContext.SqlSyntaxProvider)
{
}
//[Obsolete("Use the other constructors specifying an ISqlSyntaxProvider instead")]
//protected MigrationExpressionBase()
// : this(SqlSyntaxContext.SqlSyntaxProvider)
//{
//}
[Obsolete("Use the other constructors specifying an ISqlSyntaxProvider instead")]
protected MigrationExpressionBase(DatabaseProviders current, DatabaseProviders[] databaseProviders)
: this(current, databaseProviders, SqlSyntaxContext.SqlSyntaxProvider)
{
}
//[Obsolete("Use the other constructors specifying an ISqlSyntaxProvider instead")]
//protected MigrationExpressionBase(DatabaseProviders current, DatabaseProviders[] databaseProviders)
// : this(current, databaseProviders, SqlSyntaxContext.SqlSyntaxProvider)
//{
//}
protected MigrationExpressionBase(ISqlSyntaxProvider sqlSyntax)
{
SqlSyntax = sqlSyntax;
}
//protected MigrationExpressionBase(ISqlSyntaxProvider sqlSyntax)
//{
// SqlSyntax = sqlSyntax;
//}
protected MigrationExpressionBase(DatabaseProviders current, DatabaseProviders[] databaseProviders, ISqlSyntaxProvider sqlSyntax)
{
@@ -76,8 +76,10 @@ namespace Umbraco.Core.Persistence.Migrations
case TypeCode.UInt32:
case TypeCode.UInt64:
return val.ToString();
case TypeCode.DateTime:
return SqlSyntax.GetQuotedValue(SqlSyntax.FormatDateTime((DateTime) val));
default:
return SqlSyntaxContext.SqlSyntaxProvider.GetQuotedValue(val.ToString());
return SqlSyntax.GetQuotedValue(val.ToString());
}
}
}
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using log4net;
using Semver;
using Umbraco.Core.Configuration;
@@ -243,13 +245,43 @@ namespace Umbraco.Core.Persistence.Migrations
//TODO: We should output all of these SQL calls to files in a migration folder in App_Data/TEMP
// so if people want to executed them manually on another environment, they can.
_logger.Info<MigrationRunner>("Executing sql statement " + i + ": " + sql);
database.Execute(sql);
//The following ensures the multiple statement sare executed one at a time, this is a requirement
// of SQLCE, it's unfortunate but necessary.
// http://stackoverflow.com/questions/13665491/sql-ce-inconsistent-with-multiple-statements
var sb = new StringBuilder();
using (var reader = new StringReader(sql))
{
string line;
while ((line = reader.ReadLine()) != null)
{
line = line.Trim();
if (line.Equals("GO", StringComparison.OrdinalIgnoreCase))
{
//Execute the SQL up to the point of a GO statement
var exeSql = sb.ToString();
_logger.Info<MigrationRunner>("Executing sql statement " + i + ": " + exeSql);
database.Execute(exeSql);
//restart the string builder
sb.Remove(0, sb.Length);
}
else
{
sb.AppendLine(line);
}
}
//execute anything remaining
if (sb.Length > 0)
{
var exeSql = sb.ToString();
_logger.Info<MigrationRunner>("Executing sql statement " + i + ": " + exeSql);
database.Execute(exeSql);
}
}
i++;
}
transaction.Complete();
//Now that this is all complete, we need to add an entry to the migrations table flagging that migrations
@@ -1,30 +1,35 @@
using Umbraco.Core.Persistence.Migrations.Syntax.Alter.Column;
using Umbraco.Core.Persistence.Migrations.Syntax.Alter.Expressions;
using Umbraco.Core.Persistence.Migrations.Syntax.Alter.Table;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter
{
public class AlterSyntaxBuilder : IAlterSyntaxBuilder
{
private readonly IMigrationContext _context;
private readonly ISqlSyntaxProvider _sqlSyntax;
private readonly DatabaseProviders[] _databaseProviders;
public AlterSyntaxBuilder(IMigrationContext context)
public AlterSyntaxBuilder(IMigrationContext context, ISqlSyntaxProvider sqlSyntax, params DatabaseProviders[] databaseProviders)
{
_context = context;
_sqlSyntax = sqlSyntax;
_databaseProviders = databaseProviders;
}
public IAlterTableSyntax Table(string tableName)
{
var expression = new AlterTableExpression { TableName = tableName };
var expression = new AlterTableExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax) { TableName = tableName };
//_context.Expressions.Add(expression);
return new AlterTableBuilder(expression, _context);
return new AlterTableBuilder(_context, _databaseProviders, expression);
}
public IAlterColumnSyntax Column(string columnName)
{
var expression = new AlterColumnExpression { Column = { Name = columnName } };
var expression = new AlterColumnExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax) {Column = {Name = columnName}};
//_context.Expressions.Add(expression);
return new AlterColumnBuilder(expression, _context);
return new AlterColumnBuilder(_context, _databaseProviders, expression);
}
}
}
@@ -2,6 +2,7 @@
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.Migrations.Syntax.Alter.Expressions;
using Umbraco.Core.Persistence.Migrations.Syntax.Expressions;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter.Column
{
@@ -11,11 +12,13 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter.Column
IAlterColumnOptionForeignKeyCascadeSyntax
{
private readonly IMigrationContext _context;
private readonly DatabaseProviders[] _databaseProviders;
public AlterColumnBuilder(AlterColumnExpression expression, IMigrationContext context)
public AlterColumnBuilder(IMigrationContext context, DatabaseProviders[] databaseProviders, AlterColumnExpression expression)
: base(expression)
{
_context = context;
_databaseProviders = databaseProviders;
}
public ForeignKeyDefinition CurrentForeignKey { get; set; }
@@ -33,7 +36,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter.Column
public IAlterColumnOptionSyntax WithDefault(SystemMethods method)
{
var dc = new AlterDefaultConstraintExpression
var dc = new AlterDefaultConstraintExpression(_context.CurrentDatabaseProvider, _databaseProviders, Expression.SqlSyntax)
{
TableName = Expression.TableName,
SchemaName = Expression.SchemaName,
@@ -51,7 +54,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter.Column
public IAlterColumnOptionSyntax WithDefaultValue(object value)
{
var dc = new AlterDefaultConstraintExpression
var dc = new AlterDefaultConstraintExpression(_context.CurrentDatabaseProvider, _databaseProviders, Expression.SqlSyntax)
{
TableName = Expression.TableName,
SchemaName = Expression.SchemaName,
@@ -81,15 +84,12 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter.Column
{
Expression.Column.IsIndexed = true;
var index = new CreateIndexExpression
{
Index = new IndexDefinition
{
Name = indexName,
SchemaName = Expression.SchemaName,
TableName = Expression.TableName
}
};
var index = new CreateIndexExpression(_context.CurrentDatabaseProvider, _databaseProviders, Expression.SqlSyntax, new IndexDefinition
{
Name = indexName,
SchemaName = Expression.SchemaName,
TableName = Expression.TableName
});
index.Index.Columns.Add(new IndexColumnDefinition
{
@@ -135,16 +135,13 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter.Column
{
Expression.Column.IsUnique = true;
var index = new CreateIndexExpression
{
Index = new IndexDefinition
{
Name = indexName,
SchemaName = Expression.SchemaName,
TableName = Expression.TableName,
IsUnique = true
}
};
var index = new CreateIndexExpression(_context.CurrentDatabaseProvider, _databaseProviders, Expression.SqlSyntax, new IndexDefinition
{
Name = indexName,
SchemaName = Expression.SchemaName,
TableName = Expression.TableName,
IsUnique = true
});
index.Index.Columns.Add(new IndexColumnDefinition
{
@@ -172,17 +169,14 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter.Column
{
Expression.Column.IsForeignKey = true;
var fk = new CreateForeignKeyExpression
{
ForeignKey = new ForeignKeyDefinition
{
Name = foreignKeyName,
PrimaryTable = primaryTableName,
PrimaryTableSchema = primaryTableSchema,
ForeignTable = Expression.TableName,
ForeignTableSchema = Expression.SchemaName
}
};
var fk = new CreateForeignKeyExpression(_context.CurrentDatabaseProvider, _databaseProviders, Expression.SqlSyntax, new ForeignKeyDefinition
{
Name = foreignKeyName,
PrimaryTable = primaryTableName,
PrimaryTableSchema = primaryTableSchema,
ForeignTable = Expression.TableName,
ForeignTableSchema = Expression.SchemaName
});
fk.ForeignKey.PrimaryColumns.Add(primaryColumnName);
fk.ForeignKey.ForeignColumns.Add(Expression.Column.Name);
@@ -212,17 +206,14 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter.Column
public IAlterColumnOptionForeignKeyCascadeSyntax ReferencedBy(string foreignKeyName, string foreignTableSchema,
string foreignTableName, string foreignColumnName)
{
var fk = new CreateForeignKeyExpression
{
ForeignKey = new ForeignKeyDefinition
{
Name = foreignKeyName,
PrimaryTable = Expression.TableName,
PrimaryTableSchema = Expression.SchemaName,
ForeignTable = foreignTableName,
ForeignTableSchema = foreignTableSchema
}
};
var fk = new CreateForeignKeyExpression(_context.CurrentDatabaseProvider, _databaseProviders, Expression.SqlSyntax, new ForeignKeyDefinition
{
Name = foreignKeyName,
PrimaryTable = Expression.TableName,
PrimaryTableSchema = Expression.SchemaName,
ForeignTable = foreignTableName,
ForeignTableSchema = foreignTableSchema
});
fk.ForeignKey.PrimaryColumns.Add(Expression.Column.Name);
fk.ForeignKey.ForeignColumns.Add(foreignColumnName);
@@ -6,11 +6,11 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter.Expressions
{
public class AlterColumnExpression : MigrationExpressionBase
{
public AlterColumnExpression(ISqlSyntaxProvider sqlSyntax)
: base(sqlSyntax)
{
Column = new ColumnDefinition() { ModificationType = ModificationType.Alter };
}
//public AlterColumnExpression(ISqlSyntaxProvider sqlSyntax)
// : base(sqlSyntax)
//{
// Column = new ColumnDefinition() { ModificationType = ModificationType.Alter };
//}
public AlterColumnExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders, ISqlSyntaxProvider sqlSyntax)
: base(current, databaseProviders, sqlSyntax)
@@ -18,17 +18,17 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter.Expressions
Column = new ColumnDefinition() { ModificationType = ModificationType.Alter };
}
[Obsolete("Use the constructor specifying an ISqlSyntaxProvider instead")]
public AlterColumnExpression()
: this(SqlSyntaxContext.SqlSyntaxProvider)
{
}
//[Obsolete("Use the constructor specifying an ISqlSyntaxProvider instead")]
//public AlterColumnExpression()
// : this(SqlSyntaxContext.SqlSyntaxProvider)
//{
//}
[Obsolete("Use the constructor specifying an ISqlSyntaxProvider instead")]
public AlterColumnExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders)
: this(current, databaseProviders, SqlSyntaxContext.SqlSyntaxProvider)
{
}
//[Obsolete("Use the constructor specifying an ISqlSyntaxProvider instead")]
//public AlterColumnExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders)
// : this(current, databaseProviders, SqlSyntaxContext.SqlSyntaxProvider)
//{
//}
@@ -42,9 +42,9 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter.Expressions
// SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName(Column.Name),
// SqlSyntaxContext.SqlSyntaxProvider.Format(Column));
return string.Format(SqlSyntaxContext.SqlSyntaxProvider.AlterColumn,
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(TableName),
SqlSyntaxContext.SqlSyntaxProvider.Format(Column));
return string.Format(SqlSyntax.AlterColumn,
SqlSyntax.GetQuotedTableName(TableName),
SqlSyntax.Format(Column));
//return string.Format(SqlSyntaxContext.SqlSyntaxProvider.AlterColumn,
// SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(TableName),
@@ -4,11 +4,8 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter.Expressions
{
public class AlterDefaultConstraintExpression : MigrationExpressionBase
{
public AlterDefaultConstraintExpression()
{
}
public AlterDefaultConstraintExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders) : base(current, databaseProviders)
public AlterDefaultConstraintExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders, ISqlSyntaxProvider sqlSyntax)
: base(current, databaseProviders, sqlSyntax)
{
}
@@ -22,9 +19,9 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter.Expressions
{
//NOTE Should probably investigate if Deleting a Default Constraint is different from deleting a 'regular' constraint
return string.Format(SqlSyntaxContext.SqlSyntaxProvider.DeleteConstraint,
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(TableName),
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedName(ConstraintName));
return string.Format(SqlSyntax.DeleteConstraint,
SqlSyntax.GetQuotedTableName(TableName),
SqlSyntax.GetQuotedName(ConstraintName));
}
}
}
@@ -1,12 +1,12 @@
namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter.Expressions
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter.Expressions
{
public class AlterTableExpression : MigrationExpressionBase
{
public AlterTableExpression()
{
}
public AlterTableExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders) : base(current, databaseProviders)
public AlterTableExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders, ISqlSyntaxProvider sqlSyntax)
: base(current, databaseProviders, sqlSyntax)
{
}
@@ -2,6 +2,7 @@
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.Migrations.Syntax.Alter.Expressions;
using Umbraco.Core.Persistence.Migrations.Syntax.Expressions;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter.Table
{
@@ -10,11 +11,13 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter.Table
IAlterTableColumnOptionForeignKeyCascadeSyntax
{
private readonly IMigrationContext _context;
private readonly DatabaseProviders[] _databaseProviders;
public AlterTableBuilder(AlterTableExpression expression, IMigrationContext context)
public AlterTableBuilder(IMigrationContext context, DatabaseProviders[] databaseProviders, AlterTableExpression expression)
: base(expression)
{
_context = context;
_databaseProviders = databaseProviders;
}
public ColumnDefinition CurrentColumn { get; set; }
@@ -36,7 +39,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter.Table
{
if (CurrentColumn.ModificationType == ModificationType.Alter)
{
var dc = new AlterDefaultConstraintExpression
var dc = new AlterDefaultConstraintExpression(_context.CurrentDatabaseProvider, _databaseProviders, Expression.SqlSyntax)
{
TableName = Expression.TableName,
SchemaName = Expression.SchemaName,
@@ -66,15 +69,12 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter.Table
{
CurrentColumn.IsIndexed = true;
var index = new CreateIndexExpression
{
Index = new IndexDefinition
{
Name = indexName,
SchemaName = Expression.SchemaName,
TableName = Expression.TableName
}
};
var index = new CreateIndexExpression(_context.CurrentDatabaseProvider, _databaseProviders, Expression.SqlSyntax, new IndexDefinition
{
Name = indexName,
SchemaName = Expression.SchemaName,
TableName = Expression.TableName
});
index.Index.Columns.Add(new IndexColumnDefinition
{
@@ -120,16 +120,13 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter.Table
{
CurrentColumn.IsUnique = true;
var index = new CreateIndexExpression
{
Index = new IndexDefinition
{
Name = indexName,
SchemaName = Expression.SchemaName,
TableName = Expression.TableName,
IsUnique = true
}
};
var index = new CreateIndexExpression(_context.CurrentDatabaseProvider, _databaseProviders, Expression.SqlSyntax, new IndexDefinition
{
Name = indexName,
SchemaName = Expression.SchemaName,
TableName = Expression.TableName,
IsUnique = true
});
index.Index.Columns.Add(new IndexColumnDefinition
{
@@ -157,17 +154,14 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter.Table
{
CurrentColumn.IsForeignKey = true;
var fk = new CreateForeignKeyExpression
{
ForeignKey = new ForeignKeyDefinition
{
Name = foreignKeyName,
PrimaryTable = primaryTableName,
PrimaryTableSchema = primaryTableSchema,
ForeignTable = Expression.TableName,
ForeignTableSchema = Expression.SchemaName
}
};
var fk = new CreateForeignKeyExpression(_context.CurrentDatabaseProvider, _databaseProviders, Expression.SqlSyntax, new ForeignKeyDefinition
{
Name = foreignKeyName,
PrimaryTable = primaryTableName,
PrimaryTableSchema = primaryTableSchema,
ForeignTable = Expression.TableName,
ForeignTableSchema = Expression.SchemaName
});
fk.ForeignKey.PrimaryColumns.Add(primaryColumnName);
fk.ForeignKey.ForeignColumns.Add(CurrentColumn.Name);
@@ -197,17 +191,14 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter.Table
public IAlterTableColumnOptionForeignKeyCascadeSyntax ReferencedBy(string foreignKeyName, string foreignTableSchema,
string foreignTableName, string foreignColumnName)
{
var fk = new CreateForeignKeyExpression
{
ForeignKey = new ForeignKeyDefinition
{
Name = foreignKeyName,
PrimaryTable = Expression.TableName,
PrimaryTableSchema = Expression.SchemaName,
ForeignTable = foreignTableName,
ForeignTableSchema = foreignTableSchema
}
};
var fk = new CreateForeignKeyExpression(_context.CurrentDatabaseProvider, _databaseProviders, Expression.SqlSyntax, new ForeignKeyDefinition
{
Name = foreignKeyName,
PrimaryTable = Expression.TableName,
PrimaryTableSchema = Expression.SchemaName,
ForeignTable = foreignTableName,
ForeignTableSchema = foreignTableSchema
});
fk.ForeignKey.PrimaryColumns.Add(CurrentColumn.Name);
fk.ForeignKey.ForeignColumns.Add(foreignColumnName);
@@ -220,7 +211,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter.Table
public IAlterTableColumnTypeSyntax AddColumn(string name)
{
var column = new ColumnDefinition { Name = name, ModificationType = ModificationType.Create };
var createColumn = new CreateColumnExpression
var createColumn = new CreateColumnExpression(_context.CurrentDatabaseProvider, _databaseProviders, Expression.SqlSyntax)
{
Column = column,
SchemaName = Expression.SchemaName,
@@ -236,12 +227,12 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter.Table
public IAlterTableColumnTypeSyntax AlterColumn(string name)
{
var column = new ColumnDefinition { Name = name, ModificationType = ModificationType.Alter };
var alterColumn = new AlterColumnExpression
{
Column = column,
SchemaName = Expression.SchemaName,
TableName = Expression.TableName
};
var alterColumn = new AlterColumnExpression(_context.CurrentDatabaseProvider, _databaseProviders, Expression.SqlSyntax)
{
Column = column,
SchemaName = Expression.SchemaName,
TableName = Expression.TableName
};
CurrentColumn = column;
@@ -1,6 +1,7 @@
using System.Data;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.Migrations.Syntax.Expressions;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Syntax.Create.Column
{
@@ -10,11 +11,13 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create.Column
ICreateColumnOptionForeignKeyCascadeSyntax
{
private readonly IMigrationContext _context;
private readonly DatabaseProviders[] _databaseProviders;
public CreateColumnBuilder(CreateColumnExpression expression, IMigrationContext context)
public CreateColumnBuilder(IMigrationContext context, DatabaseProviders[] databaseProviders, CreateColumnExpression expression)
: base(expression)
{
_context = context;
_databaseProviders = databaseProviders;
}
public ForeignKeyDefinition CurrentForeignKey { get; set; }
@@ -56,15 +59,12 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create.Column
{
Expression.Column.IsIndexed = true;
var index = new CreateIndexExpression
{
Index = new IndexDefinition
{
Name = indexName,
SchemaName = Expression.SchemaName,
TableName = Expression.TableName
}
};
var index = new CreateIndexExpression(_context.CurrentDatabaseProvider, _databaseProviders, Expression.SqlSyntax, new IndexDefinition
{
Name = indexName,
SchemaName = Expression.SchemaName,
TableName = Expression.TableName
});
index.Index.Columns.Add(new IndexColumnDefinition
{
@@ -110,16 +110,13 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create.Column
{
Expression.Column.IsUnique = true;
var index = new CreateIndexExpression
{
Index = new IndexDefinition
{
Name = indexName,
SchemaName = Expression.SchemaName,
TableName = Expression.TableName,
IsUnique = true
}
};
var index = new CreateIndexExpression(_context.CurrentDatabaseProvider, _databaseProviders, Expression.SqlSyntax, new IndexDefinition
{
Name = indexName,
SchemaName = Expression.SchemaName,
TableName = Expression.TableName,
IsUnique = true
});
index.Index.Columns.Add(new IndexColumnDefinition
{
@@ -147,17 +144,14 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create.Column
{
Expression.Column.IsForeignKey = true;
var fk = new CreateForeignKeyExpression
{
ForeignKey = new ForeignKeyDefinition
{
Name = foreignKeyName,
PrimaryTable = primaryTableName,
PrimaryTableSchema = primaryTableSchema,
ForeignTable = Expression.TableName,
ForeignTableSchema = Expression.SchemaName
}
};
var fk = new CreateForeignKeyExpression(_context.CurrentDatabaseProvider, _databaseProviders, Expression.SqlSyntax, new ForeignKeyDefinition
{
Name = foreignKeyName,
PrimaryTable = primaryTableName,
PrimaryTableSchema = primaryTableSchema,
ForeignTable = Expression.TableName,
ForeignTableSchema = Expression.SchemaName
});
fk.ForeignKey.PrimaryColumns.Add(primaryColumnName);
fk.ForeignKey.ForeignColumns.Add(Expression.Column.Name);
@@ -187,17 +181,14 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create.Column
public ICreateColumnOptionForeignKeyCascadeSyntax ReferencedBy(string foreignKeyName, string foreignTableSchema,
string foreignTableName, string foreignColumnName)
{
var fk = new CreateForeignKeyExpression
{
ForeignKey = new ForeignKeyDefinition
{
Name = foreignKeyName,
PrimaryTable = Expression.TableName,
PrimaryTableSchema = Expression.SchemaName,
ForeignTable = foreignTableName,
ForeignTableSchema = foreignTableSchema
}
};
var fk = new CreateForeignKeyExpression(_context.CurrentDatabaseProvider, _databaseProviders, Expression.SqlSyntax, new ForeignKeyDefinition
{
Name = foreignKeyName,
PrimaryTable = Expression.TableName,
PrimaryTableSchema = Expression.SchemaName,
ForeignTable = foreignTableName,
ForeignTableSchema = foreignTableSchema
});
fk.ForeignKey.PrimaryColumns.Add(Expression.Column.Name);
fk.ForeignKey.ForeignColumns.Add(foreignColumnName);
@@ -19,75 +19,66 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create
public CreateBuilder(IMigrationContext context, ISqlSyntaxProvider sqlSyntax, params DatabaseProviders[] databaseProviders)
{
if (context == null) throw new ArgumentNullException("context");
if (sqlSyntax == null) throw new ArgumentNullException("sqlSyntax");
_context = context;
_sqlSyntax = sqlSyntax;
_databaseProviders = databaseProviders;
}
[Obsolete("Use alternate ctor specifying ISqlSyntaxProvider instead")]
public CreateBuilder(IMigrationContext context, params DatabaseProviders[] databaseProviders)
:this(context, SqlSyntaxContext.SqlSyntaxProvider, databaseProviders)
{
}
public ICreateTableWithColumnSyntax Table(string tableName)
{
var expression = new CreateTableExpression { TableName = tableName };
var expression = new CreateTableExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax) { TableName = tableName };
_context.Expressions.Add(expression);
return new CreateTableBuilder(expression, _context);
return new CreateTableBuilder(_context, _databaseProviders, expression);
}
public ICreateColumnOnTableSyntax Column(string columnName)
{
var expression = _databaseProviders == null
? new CreateColumnExpression { Column = { Name = columnName } }
: new CreateColumnExpression(_context.CurrentDatabaseProvider, _databaseProviders) { Column = { Name = columnName } };
var expression = new CreateColumnExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax) { Column = { Name = columnName } };
_context.Expressions.Add(expression);
return new CreateColumnBuilder(expression, _context);
return new CreateColumnBuilder(_context, _databaseProviders, expression);
}
public ICreateForeignKeyFromTableSyntax ForeignKey()
{
var expression = _databaseProviders == null
? new CreateForeignKeyExpression()
: new CreateForeignKeyExpression(_context.CurrentDatabaseProvider, _databaseProviders);
var expression = new CreateForeignKeyExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax);
_context.Expressions.Add(expression);
return new CreateForeignKeyBuilder(expression);
}
public ICreateForeignKeyFromTableSyntax ForeignKey(string foreignKeyName)
{
var expression = _databaseProviders == null
? new CreateForeignKeyExpression { ForeignKey = { Name = foreignKeyName } }
: new CreateForeignKeyExpression(_context.CurrentDatabaseProvider, _databaseProviders) { ForeignKey = { Name = foreignKeyName } };
var expression = new CreateForeignKeyExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax) { ForeignKey = { Name = foreignKeyName } };
_context.Expressions.Add(expression);
return new CreateForeignKeyBuilder(expression);
}
public ICreateIndexForTableSyntax Index()
{
var expression = new CreateIndexExpression(_sqlSyntax);
var expression = new CreateIndexExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax);
_context.Expressions.Add(expression);
return new CreateIndexBuilder(expression);
}
public ICreateIndexForTableSyntax Index(string indexName)
{
var expression = new CreateIndexExpression(_sqlSyntax) { Index = { Name = indexName } };
var expression = new CreateIndexExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax) { Index = { Name = indexName } };
_context.Expressions.Add(expression);
return new CreateIndexBuilder(expression);
}
public ICreateConstraintOnTableSyntax PrimaryKey()
{
var expression = new CreateConstraintExpression(ConstraintType.PrimaryKey);
var expression = new CreateConstraintExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax, ConstraintType.PrimaryKey);
_context.Expressions.Add(expression);
return new CreateConstraintBuilder(expression);
}
public ICreateConstraintOnTableSyntax PrimaryKey(string primaryKeyName)
{
var expression = new CreateConstraintExpression(ConstraintType.PrimaryKey);
var expression = new CreateConstraintExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax, ConstraintType.PrimaryKey);
expression.Constraint.ConstraintName = primaryKeyName;
_context.Expressions.Add(expression);
return new CreateConstraintBuilder(expression);
@@ -95,14 +86,14 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create
public ICreateConstraintOnTableSyntax UniqueConstraint()
{
var expression = new CreateConstraintExpression(ConstraintType.Unique);
var expression = new CreateConstraintExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax, ConstraintType.Unique);
_context.Expressions.Add(expression);
return new CreateConstraintBuilder(expression);
}
public ICreateConstraintOnTableSyntax UniqueConstraint(string constraintName)
{
var expression = new CreateConstraintExpression(ConstraintType.Unique);
var expression = new CreateConstraintExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax, ConstraintType.Unique);
expression.Constraint.ConstraintName = constraintName;
_context.Expressions.Add(expression);
return new CreateConstraintBuilder(expression);
@@ -110,7 +101,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create
public ICreateConstraintOnTableSyntax Constraint(string constraintName)
{
var expression = new CreateConstraintExpression(ConstraintType.NonUnique);
var expression = new CreateConstraintExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax, ConstraintType.NonUnique);
expression.Constraint.ConstraintName = constraintName;
_context.Expressions.Add(expression);
return new CreateConstraintBuilder(expression);
@@ -6,10 +6,12 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create.Expressions
{
public class CreateConstraintExpression : MigrationExpressionBase
{
public CreateConstraintExpression(ConstraintType type)
public CreateConstraintExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders, ISqlSyntaxProvider sqlSyntax, ConstraintType constraint)
: base(current, databaseProviders, sqlSyntax)
{
Constraint = new ConstraintDefinition(type);
Constraint = new ConstraintDefinition(constraint);
}
public ConstraintDefinition Constraint { get; private set; }
@@ -17,7 +19,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create.Expressions
{
var constraintType = (Constraint.IsPrimaryKeyConstraint) ? "PRIMARY KEY" : "UNIQUE";
if (Constraint.IsPrimaryKeyConstraint && SqlSyntaxContext.SqlSyntaxProvider.SupportsClustered())
if (Constraint.IsPrimaryKeyConstraint && SqlSyntax.SupportsClustered())
constraintType += " CLUSTERED";
if (Constraint.IsNonUniqueConstraint)
@@ -27,12 +29,12 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create.Expressions
for (int i = 0; i < Constraint.Columns.Count; i++)
{
columns[i] = SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName(Constraint.Columns.ElementAt(i));
columns[i] = SqlSyntax.GetQuotedColumnName(Constraint.Columns.ElementAt(i));
}
return string.Format(SqlSyntaxContext.SqlSyntaxProvider.CreateConstraint,
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(Constraint.TableName),
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedName(Constraint.ConstraintName),
return string.Format(SqlSyntax.CreateConstraint,
SqlSyntax.GetQuotedTableName(Constraint.TableName),
SqlSyntax.GetQuotedName(Constraint.ConstraintName),
constraintType,
string.Join(", ", columns));
}
@@ -7,24 +7,24 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create.Expressions
{
public class CreateTableExpression : MigrationExpressionBase
{
[Obsolete("Use the other constructors specifying an ISqlSyntaxProvider instead")]
public CreateTableExpression()
{
Columns = new List<ColumnDefinition>();
}
//[Obsolete("Use the other constructors specifying an ISqlSyntaxProvider instead")]
//public CreateTableExpression()
//{
// Columns = new List<ColumnDefinition>();
//}
[Obsolete("Use the other constructors specifying an ISqlSyntaxProvider instead")]
public CreateTableExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders)
: base(current, databaseProviders)
{
Columns = new List<ColumnDefinition>();
}
//[Obsolete("Use the other constructors specifying an ISqlSyntaxProvider instead")]
//public CreateTableExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders)
// : base(current, databaseProviders)
//{
// Columns = new List<ColumnDefinition>();
//}
public CreateTableExpression(ISqlSyntaxProvider sqlSyntax)
: base(sqlSyntax)
{
Columns = new List<ColumnDefinition>();
}
//public CreateTableExpression(ISqlSyntaxProvider sqlSyntax)
// : base(sqlSyntax)
//{
// Columns = new List<ColumnDefinition>();
//}
public CreateTableExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders, ISqlSyntaxProvider sqlSyntax)
: base(current, databaseProviders, sqlSyntax)
@@ -2,6 +2,7 @@
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.Migrations.Syntax.Create.Expressions;
using Umbraco.Core.Persistence.Migrations.Syntax.Expressions;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Syntax.Create.Table
{
@@ -11,11 +12,13 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create.Table
ICreateTableColumnOptionForeignKeyCascadeSyntax
{
private readonly IMigrationContext _context;
private readonly DatabaseProviders[] _databaseProviders;
public CreateTableBuilder(CreateTableExpression expression, IMigrationContext context)
public CreateTableBuilder(IMigrationContext context, DatabaseProviders[] databaseProviders, CreateTableExpression expression)
: base(expression)
{
_context = context;
_databaseProviders = databaseProviders;
}
public ColumnDefinition CurrentColumn { get; set; }
@@ -62,15 +65,12 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create.Table
{
CurrentColumn.IsIndexed = true;
var index = new CreateIndexExpression
{
Index = new IndexDefinition
{
Name = indexName,
SchemaName = Expression.SchemaName,
TableName = Expression.TableName
}
};
var index = new CreateIndexExpression(_context.CurrentDatabaseProvider, _databaseProviders, Expression.SqlSyntax, new IndexDefinition
{
Name = indexName,
SchemaName = Expression.SchemaName,
TableName = Expression.TableName
});
index.Index.Columns.Add(new IndexColumnDefinition
{
@@ -86,15 +86,25 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create.Table
{
CurrentColumn.IsPrimaryKey = true;
var expression = new CreateConstraintExpression(ConstraintType.PrimaryKey)
//For MySQL, the PK will be created WITH the create table expression, however for
// SQL Server, the PK get's created in a different Alter table expression afterwords.
// MySQL will choke if the same constraint is again added afterword
// TODO: This is a super hack, I'd rather not add another property like 'CreatesPkInCreateTableDefinition' to check
// for this, but I don't see another way around. MySQL doesn't support checking for a constraint before creating
// it... except in a very strange way but it doesn't actually provider error feedback if it doesn't work so we cannot use
// it. For now, this is what I'm doing
if (Expression.CurrentDatabaseProvider != DatabaseProviders.MySql)
{
Constraint =
var expression = new CreateConstraintExpression(_context.CurrentDatabaseProvider, _databaseProviders, Expression.SqlSyntax, ConstraintType.PrimaryKey)
{
Constraint =
{
TableName = CurrentColumn.TableName,
Columns = new[] { CurrentColumn.Name }
}
};
_context.Expressions.Add(expression);
};
_context.Expressions.Add(expression);
}
return this;
}
@@ -104,16 +114,27 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create.Table
CurrentColumn.IsPrimaryKey = true;
CurrentColumn.PrimaryKeyName = primaryKeyName;
var expression = new CreateConstraintExpression(ConstraintType.PrimaryKey)
//For MySQL, the PK will be created WITH the create table expression, however for
// SQL Server, the PK get's created in a different Alter table expression afterwords.
// MySQL will choke if the same constraint is again added afterword
// TODO: This is a super hack, I'd rather not add another property like 'CreatesPkInCreateTableDefinition' to check
// for this, but I don't see another way around. MySQL doesn't support checking for a constraint before creating
// it... except in a very strange way but it doesn't actually provider error feedback if it doesn't work so we cannot use
// it. For now, this is what I'm doing
if (Expression.CurrentDatabaseProvider != DatabaseProviders.MySql)
{
Constraint =
var expression = new CreateConstraintExpression(_context.CurrentDatabaseProvider, _databaseProviders, Expression.SqlSyntax, ConstraintType.PrimaryKey)
{
Constraint =
{
ConstraintName = primaryKeyName,
TableName = CurrentColumn.TableName,
Columns = new[] { CurrentColumn.Name }
}
};
_context.Expressions.Add(expression);
};
_context.Expressions.Add(expression);
}
return this;
}
@@ -139,16 +160,13 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create.Table
{
CurrentColumn.IsUnique = true;
var index = new CreateIndexExpression
{
Index = new IndexDefinition
{
Name = indexName,
SchemaName = Expression.SchemaName,
TableName = Expression.TableName,
IsUnique = true
}
};
var index = new CreateIndexExpression(_context.CurrentDatabaseProvider, _databaseProviders, Expression.SqlSyntax, new IndexDefinition
{
Name = indexName,
SchemaName = Expression.SchemaName,
TableName = Expression.TableName,
IsUnique = true
});
index.Index.Columns.Add(new IndexColumnDefinition
{
@@ -176,17 +194,14 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create.Table
{
CurrentColumn.IsForeignKey = true;
var fk = new CreateForeignKeyExpression
{
ForeignKey = new ForeignKeyDefinition
{
Name = foreignKeyName,
PrimaryTable = primaryTableName,
PrimaryTableSchema = primaryTableSchema,
ForeignTable = Expression.TableName,
ForeignTableSchema = Expression.SchemaName
}
};
var fk = new CreateForeignKeyExpression(_context.CurrentDatabaseProvider, _databaseProviders, Expression.SqlSyntax, new ForeignKeyDefinition
{
Name = foreignKeyName,
PrimaryTable = primaryTableName,
PrimaryTableSchema = primaryTableSchema,
ForeignTable = Expression.TableName,
ForeignTableSchema = Expression.SchemaName
});
fk.ForeignKey.PrimaryColumns.Add(primaryColumnName);
fk.ForeignKey.ForeignColumns.Add(CurrentColumn.Name);
@@ -216,17 +231,14 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create.Table
public ICreateTableColumnOptionForeignKeyCascadeSyntax ReferencedBy(string foreignKeyName, string foreignTableSchema,
string foreignTableName, string foreignColumnName)
{
var fk = new CreateForeignKeyExpression
{
ForeignKey = new ForeignKeyDefinition
{
Name = foreignKeyName,
PrimaryTable = Expression.TableName,
PrimaryTableSchema = Expression.SchemaName,
ForeignTable = foreignTableName,
ForeignTableSchema = foreignTableSchema
}
};
var fk = new CreateForeignKeyExpression(_context.CurrentDatabaseProvider, _databaseProviders, Expression.SqlSyntax, new ForeignKeyDefinition
{
Name = foreignKeyName,
PrimaryTable = Expression.TableName,
PrimaryTableSchema = Expression.SchemaName,
ForeignTable = foreignTableName,
ForeignTableSchema = foreignTableSchema
});
fk.ForeignKey.PrimaryColumns.Add(CurrentColumn.Name);
fk.ForeignKey.ForeignColumns.Add(foreignColumnName);
@@ -23,69 +23,57 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete
_databaseProviders = databaseProviders;
}
[Obsolete("Use the other constructor specifying an ISqlSyntaxProvider instead")]
public DeleteBuilder(IMigrationContext context, params DatabaseProviders[] databaseProviders)
: this(context, SqlSyntaxContext.SqlSyntaxProvider, databaseProviders)
{
}
public void Table(string tableName)
{
var expression = new DeleteTableExpression { TableName = tableName };
var expression = new DeleteTableExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax) { TableName = tableName };
_context.Expressions.Add(expression);
}
public IDeleteColumnFromTableSyntax Column(string columnName)
{
var expression = _databaseProviders == null
? new DeleteColumnExpression { ColumnNames = { columnName } }
: new DeleteColumnExpression(_context.CurrentDatabaseProvider, _databaseProviders) { ColumnNames = { columnName } };
var expression = new DeleteColumnExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax) {ColumnNames = {columnName}};
_context.Expressions.Add(expression);
return new DeleteColumnBuilder(expression);
}
public IDeleteForeignKeyFromTableSyntax ForeignKey()
{
var expression = _databaseProviders == null
? new DeleteForeignKeyExpression(_sqlSyntax)
: new DeleteForeignKeyExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax);
var expression = new DeleteForeignKeyExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax);
_context.Expressions.Add(expression);
return new DeleteForeignKeyBuilder(expression);
}
public IDeleteForeignKeyOnTableSyntax ForeignKey(string foreignKeyName)
{
var expression = _databaseProviders == null
? new DeleteForeignKeyExpression(_sqlSyntax) { ForeignKey = { Name = foreignKeyName } }
: new DeleteForeignKeyExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax) { ForeignKey = { Name = foreignKeyName } };
var expression = new DeleteForeignKeyExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax) {ForeignKey = {Name = foreignKeyName}};
_context.Expressions.Add(expression);
return new DeleteForeignKeyBuilder(expression);
}
public IDeleteDataSyntax FromTable(string tableName)
{
var expression = new DeleteDataExpression { TableName = tableName };
var expression = new DeleteDataExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax) { TableName = tableName };
_context.Expressions.Add(expression);
return new DeleteDataBuilder(expression);
}
public IDeleteIndexForTableSyntax Index()
{
var expression = new DeleteIndexExpression();
var expression = new DeleteIndexExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax);
_context.Expressions.Add(expression);
return new DeleteIndexBuilder(expression);
}
public IDeleteIndexForTableSyntax Index(string indexName)
{
var expression = new DeleteIndexExpression { Index = { Name = indexName } };
var expression = new DeleteIndexExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax) { Index = { Name = indexName } };
_context.Expressions.Add(expression);
return new DeleteIndexBuilder(expression);
}
public IDeleteConstraintOnTableSyntax PrimaryKey(string primaryKeyName)
{
var expression = new DeleteConstraintExpression(_context.CurrentDatabaseProvider, _databaseProviders, ConstraintType.PrimaryKey)
var expression = new DeleteConstraintExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax, ConstraintType.PrimaryKey)
{
Constraint = { ConstraintName = primaryKeyName }
};
@@ -95,7 +83,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete
public IDeleteConstraintOnTableSyntax UniqueConstraint(string constraintName)
{
var expression = new DeleteConstraintExpression(ConstraintType.Unique)
var expression = new DeleteConstraintExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax, ConstraintType.Unique)
{
Constraint = { ConstraintName = constraintName }
};
@@ -105,9 +93,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete
public IDeleteDefaultConstraintOnTableSyntax DefaultConstraint()
{
var expression = _databaseProviders == null
? new DeleteDefaultConstraintExpression()
: new DeleteDefaultConstraintExpression(_context.CurrentDatabaseProvider, _databaseProviders);
var expression = new DeleteDefaultConstraintExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax);
_context.Expressions.Add(expression);
return new DeleteDefaultConstraintBuilder(expression);
}
@@ -7,13 +7,13 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions
{
public class DeleteColumnExpression : MigrationExpressionBase
{
public DeleteColumnExpression()
{
ColumnNames = new List<string>();
}
//public DeleteColumnExpression()
//{
// ColumnNames = new List<string>();
//}
public DeleteColumnExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders)
: base(current, databaseProviders)
public DeleteColumnExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders, ISqlSyntaxProvider sqlSyntax)
: base(current, databaseProviders, sqlSyntax)
{
ColumnNames = new List<string>();
}
@@ -31,9 +31,9 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions
foreach (string columnName in ColumnNames)
{
if (ColumnNames.First() != columnName) sb.AppendLine(";");
sb.AppendFormat(SqlSyntaxContext.SqlSyntaxProvider.DropColumn,
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(TableName),
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName(columnName));
sb.AppendFormat(SqlSyntax.DropColumn,
SqlSyntax.GetQuotedTableName(TableName),
SqlSyntax.GetQuotedColumnName(columnName));
}
return sb.ToString();
@@ -5,13 +5,9 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions
{
public class DeleteConstraintExpression : MigrationExpressionBase
{
public DeleteConstraintExpression(ConstraintType type)
{
Constraint = new ConstraintDefinition(type);
}
public DeleteConstraintExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders, ConstraintType type)
: base(current, databaseProviders)
public DeleteConstraintExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders, ISqlSyntaxProvider sqlSyntax, ConstraintType type)
: base(current, databaseProviders, sqlSyntax)
{
Constraint = new ConstraintDefinition(type);
}
@@ -25,24 +21,24 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions
{
if (Constraint.IsPrimaryKeyConstraint)
{
return string.Format(SqlSyntaxContext.SqlSyntaxProvider.DeleteConstraint,
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(Constraint.TableName),
return string.Format(SqlSyntax.DeleteConstraint,
SqlSyntax.GetQuotedTableName(Constraint.TableName),
"PRIMARY KEY",
"");
}
else
{
return string.Format(SqlSyntaxContext.SqlSyntaxProvider.DeleteConstraint,
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(Constraint.TableName),
return string.Format(SqlSyntax.DeleteConstraint,
SqlSyntax.GetQuotedTableName(Constraint.TableName),
"FOREIGN KEY",
"");
}
}
else
{
return string.Format(SqlSyntaxContext.SqlSyntaxProvider.DeleteConstraint,
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(Constraint.TableName),
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedName(Constraint.ConstraintName));
return string.Format(SqlSyntax.DeleteConstraint,
SqlSyntax.GetQuotedTableName(Constraint.TableName),
SqlSyntax.GetQuotedName(Constraint.ConstraintName));
}
}
}
@@ -8,12 +8,9 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions
public class DeleteDataExpression : MigrationExpressionBase
{
private readonly List<DeletionDataDefinition> _rows = new List<DeletionDataDefinition>();
public DeleteDataExpression()
{
}
public DeleteDataExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders) : base(current, databaseProviders)
public DeleteDataExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders, ISqlSyntaxProvider sqlSyntax)
: base(current, databaseProviders, sqlSyntax)
{
}
@@ -32,7 +29,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions
if (IsAllRows)
{
deleteItems.Add(string.Format(SqlSyntaxContext.SqlSyntaxProvider.DeleteData, SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(TableName), "1 = 1"));
deleteItems.Add(string.Format(SqlSyntax.DeleteData, SqlSyntax.GetQuotedTableName(TableName), "1 = 1"));
}
else
{
@@ -42,13 +39,13 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions
foreach (KeyValuePair<string, object> item in row)
{
whereClauses.Add(string.Format("{0} {1} {2}",
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName(item.Key),
SqlSyntax.GetQuotedColumnName(item.Key),
item.Value == null ? "IS" : "=",
GetQuotedValue(item.Value)));
}
deleteItems.Add(string.Format(SqlSyntaxContext.SqlSyntaxProvider.DeleteData,
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(TableName),
deleteItems.Add(string.Format(SqlSyntax.DeleteData,
SqlSyntax.GetQuotedTableName(TableName),
String.Join(" AND ", whereClauses.ToArray())));
}
}
@@ -4,12 +4,8 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions
{
public class DeleteDefaultConstraintExpression : MigrationExpressionBase
{
public DeleteDefaultConstraintExpression()
{
}
public DeleteDefaultConstraintExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders)
: base(current, databaseProviders)
public DeleteDefaultConstraintExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders, ISqlSyntaxProvider sqlSyntax)
: base(current, databaseProviders, sqlSyntax)
{
}
@@ -22,7 +18,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions
if (IsExpressionSupported() == false)
return string.Empty;
return string.Format(SqlSyntaxContext.SqlSyntaxProvider.DeleteDefaultConstraint,
return string.Format(SqlSyntax.DeleteDefaultConstraint,
TableName,
ColumnName);
}
@@ -8,24 +8,11 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions
{
public class DeleteForeignKeyExpression : MigrationExpressionBase
{
[Obsolete("Use the other constructors specifying an ILogger instead")]
public DeleteForeignKeyExpression()
{
ForeignKey = new ForeignKeyDefinition();
}
[Obsolete("Use the other constructors specifying an ILogger instead")]
public DeleteForeignKeyExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders)
: base(current, databaseProviders)
{
ForeignKey = new ForeignKeyDefinition();
}
public DeleteForeignKeyExpression(ISqlSyntaxProvider sqlSyntax)
: base(sqlSyntax)
{
ForeignKey = new ForeignKeyDefinition();
}
//public DeleteForeignKeyExpression(ISqlSyntaxProvider sqlSyntax)
// : base(sqlSyntax)
//{
// ForeignKey = new ForeignKeyDefinition();
//}
public DeleteForeignKeyExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders, ISqlSyntaxProvider sqlSyntax)
: base(current, databaseProviders, sqlSyntax)
@@ -33,7 +20,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions
ForeignKey = new ForeignKeyDefinition();
}
public virtual ForeignKeyDefinition ForeignKey { get; set; }
public ForeignKeyDefinition ForeignKey { get; set; }
public override string ToString()
{
@@ -45,7 +32,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions
if (CurrentDatabaseProvider == DatabaseProviders.MySql)
{
//MySql naming "convention" for foreignkeys, which aren't explicitly named
//MySql naming "convention" for foreignkeys, which aren't explicitly named
if (string.IsNullOrEmpty(ForeignKey.Name))
ForeignKey.Name = string.Format("{0}_ibfk_1", ForeignKey.ForeignTable.ToLower());
@@ -5,23 +5,26 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions
{
public class DeleteIndexExpression : MigrationExpressionBase
{
public DeleteIndexExpression()
public DeleteIndexExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders, ISqlSyntaxProvider sqlSyntax)
: base(current, databaseProviders, sqlSyntax)
{
Index = new IndexDefinition();
}
public DeleteIndexExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders) : base(current, databaseProviders)
public DeleteIndexExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders, ISqlSyntaxProvider sqlSyntax, IndexDefinition index)
: base(current, databaseProviders, sqlSyntax)
{
Index = new IndexDefinition();
Index = index;
}
public virtual IndexDefinition Index { get; set; }
public IndexDefinition Index { get; private set; }
public override string ToString()
{
return string.Format(SqlSyntaxContext.SqlSyntaxProvider.DropIndex,
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedName(Index.Name),
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(Index.TableName));
return string.Format(SqlSyntax.DropIndex,
SqlSyntax.GetQuotedName(Index.Name),
SqlSyntax.GetQuotedTableName(Index.TableName));
}
}
}
@@ -4,11 +4,9 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions
{
public class DeleteTableExpression : MigrationExpressionBase
{
public DeleteTableExpression()
{
}
public DeleteTableExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders) : base(current, databaseProviders)
public DeleteTableExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders, ISqlSyntaxProvider sqlSyntax)
: base(current, databaseProviders, sqlSyntax)
{
}
@@ -17,8 +15,8 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions
public override string ToString()
{
return string.Format(SqlSyntaxContext.SqlSyntaxProvider.DropTable,
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(TableName));
return string.Format(SqlSyntax.DropTable,
SqlSyntax.GetQuotedTableName(TableName));
}
}
}
@@ -12,7 +12,6 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete
void Table(string tableName);
IDeleteColumnFromTableSyntax Column(string columnName);
IDeleteForeignKeyFromTableSyntax ForeignKey();
[Obsolete("Do not use this construct as it does not work with MySql, use the syntax: Delete.ForeignKey().FromTable(\"umbracoUser2app\").ForeignColumn(... instead")]
IDeleteForeignKeyOnTableSyntax ForeignKey(string foreignKeyName);
IDeleteDataSyntax FromTable(string tableName);
IDeleteIndexForTableSyntax Index();
@@ -1,34 +1,31 @@
using System;
using Umbraco.Core.Persistence.Migrations.Syntax.Execute.Expressions;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Syntax.Execute
{
public class ExecuteBuilder : IExecuteBuilder
{
private readonly IMigrationContext _context;
private readonly ISqlSyntaxProvider _sqlSyntax;
private readonly DatabaseProviders[] _databaseProviders;
public ExecuteBuilder(IMigrationContext context, params DatabaseProviders[] databaseProviders)
public ExecuteBuilder(IMigrationContext context, ISqlSyntaxProvider sqlSyntax, params DatabaseProviders[] databaseProviders)
{
_context = context;
_sqlSyntax = sqlSyntax;
_databaseProviders = databaseProviders;
}
public void Sql(string sqlStatement)
{
var expression = _databaseProviders == null
? new ExecuteSqlStatementExpression {SqlStatement = sqlStatement}
: new ExecuteSqlStatementExpression(_context.CurrentDatabaseProvider,
_databaseProviders) {SqlStatement = sqlStatement};
var expression = new ExecuteSqlStatementExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax) {SqlStatement = sqlStatement};
_context.Expressions.Add(expression);
}
public void Code(Func<Database, string> codeStatement)
{
var expression = _databaseProviders == null
? new ExecuteCodeStatementExpression { CodeStatement = codeStatement }
: new ExecuteCodeStatementExpression(_context.CurrentDatabaseProvider,
_databaseProviders) { CodeStatement = codeStatement };
var expression = new ExecuteCodeStatementExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax) { CodeStatement = codeStatement };
_context.Expressions.Add(expression);
}
}
@@ -1,15 +1,12 @@
using System;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Syntax.Execute.Expressions
{
public class ExecuteCodeStatementExpression : MigrationExpressionBase
{
public ExecuteCodeStatementExpression()
{
}
public ExecuteCodeStatementExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders)
: base(current, databaseProviders)
public ExecuteCodeStatementExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders, ISqlSyntaxProvider sqlSyntax)
: base(current, databaseProviders, sqlSyntax)
{
}
@@ -1,12 +1,12 @@
namespace Umbraco.Core.Persistence.Migrations.Syntax.Execute.Expressions
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Syntax.Execute.Expressions
{
public class ExecuteSqlStatementExpression : MigrationExpressionBase
{
public ExecuteSqlStatementExpression()
{
}
public ExecuteSqlStatementExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders) : base(current, databaseProviders)
public ExecuteSqlStatementExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders, ISqlSyntaxProvider sqlSyntax)
: base(current, databaseProviders, sqlSyntax)
{
}
@@ -5,20 +5,16 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Expressions
{
public class CreateColumnExpression : MigrationExpressionBase
{
public CreateColumnExpression()
public CreateColumnExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders, ISqlSyntaxProvider sqlSyntax)
: base(current, databaseProviders, sqlSyntax)
{
Column = new ColumnDefinition { ModificationType = ModificationType.Create };
}
public CreateColumnExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders)
: base(current, databaseProviders)
{
Column = new ColumnDefinition { ModificationType = ModificationType.Create };
}
public virtual string SchemaName { get; set; }
public virtual string TableName { get; set; }
public virtual ColumnDefinition Column { get; set; }
public string SchemaName { get; set; }
public string TableName { get; set; }
public ColumnDefinition Column { get; set; }
public override string ToString()
{
@@ -28,9 +24,9 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Expressions
if (string.IsNullOrEmpty(Column.TableName))
Column.TableName = TableName;
return string.Format(SqlSyntaxContext.SqlSyntaxProvider.AddColumn,
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(Column.TableName),
SqlSyntaxContext.SqlSyntaxProvider.Format(Column));
return string.Format(SqlSyntax.AddColumn,
SqlSyntax.GetQuotedTableName(Column.TableName),
SqlSyntax.Format(Column));
}
}
}
@@ -5,25 +5,26 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Expressions
{
public class CreateForeignKeyExpression : MigrationExpressionBase
{
public CreateForeignKeyExpression()
public CreateForeignKeyExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders, ISqlSyntaxProvider sqlSyntax, ForeignKeyDefinition fkDef)
: base(current, databaseProviders, sqlSyntax)
{
ForeignKey = fkDef;
}
public CreateForeignKeyExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders, ISqlSyntaxProvider sqlSyntax)
: base(current, databaseProviders, sqlSyntax)
{
ForeignKey = new ForeignKeyDefinition();
}
public CreateForeignKeyExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders)
: base(current, databaseProviders)
{
ForeignKey = new ForeignKeyDefinition();
}
public virtual ForeignKeyDefinition ForeignKey { get; set; }
public ForeignKeyDefinition ForeignKey { get; set; }
public override string ToString()
{
if (IsExpressionSupported() == false)
return string.Empty;
return SqlSyntaxContext.SqlSyntaxProvider.Format(ForeignKey);
return SqlSyntax.Format(ForeignKey);
}
}
}
@@ -6,32 +6,20 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Expressions
{
public class CreateIndexExpression : MigrationExpressionBase
{
public CreateIndexExpression(ISqlSyntaxProvider sqlSyntax)
: base(sqlSyntax)
public CreateIndexExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders, ISqlSyntaxProvider sqlSyntax, IndexDefinition index)
: base(current, databaseProviders, sqlSyntax)
{
Index = new IndexDefinition();
Index = index;
}
public CreateIndexExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders, ISqlSyntaxProvider sqlSyntax)
: base(current, databaseProviders, sqlSyntax)
{
Index = new IndexDefinition();
}
[Obsolete("Use alternate ctor specifying ISqlSyntaxProvider instead")]
public CreateIndexExpression()
: this(SqlSyntaxContext.SqlSyntaxProvider)
{
}
[Obsolete("Use alternate ctor specifying ISqlSyntaxProvider instead")]
public CreateIndexExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders)
: this(current, databaseProviders, SqlSyntaxContext.SqlSyntaxProvider)
{
}
public virtual IndexDefinition Index { get; set; }
public IndexDefinition Index { get; set; }
public override string ToString()
{
@@ -3,43 +3,46 @@ using Umbraco.Core.Persistence.Migrations.Syntax.Delete;
using Umbraco.Core.Persistence.Migrations.Syntax.Execute;
using Umbraco.Core.Persistence.Migrations.Syntax.Rename;
using Umbraco.Core.Persistence.Migrations.Syntax.Update;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Syntax.IfDatabase
{
public class IfDatabaseBuilder : IIfDatabaseBuilder
{
private readonly IMigrationContext _context;
private readonly ISqlSyntaxProvider _sqlSyntax;
private readonly DatabaseProviders[] _databaseProviders;
public IfDatabaseBuilder(IMigrationContext context, params DatabaseProviders[] databaseProviders)
public IfDatabaseBuilder(IMigrationContext context, ISqlSyntaxProvider sqlSyntax, params DatabaseProviders[] databaseProviders)
{
_context = context;
_sqlSyntax = sqlSyntax;
_databaseProviders = databaseProviders;
}
public ICreateBuilder Create
{
get { return new CreateBuilder(_context, _databaseProviders); }
get { return new CreateBuilder(_context, _sqlSyntax, _databaseProviders); }
}
public IExecuteBuilder Execute
{
get { return new ExecuteBuilder(_context, _databaseProviders); }
get { return new ExecuteBuilder(_context, _sqlSyntax, _databaseProviders); }
}
public IDeleteBuilder Delete
{
get { return new DeleteBuilder(_context, _databaseProviders); }
get { return new DeleteBuilder(_context, _sqlSyntax, _databaseProviders); }
}
public IRenameBuilder Rename
{
get { return new RenameBuilder(_context, _databaseProviders); }
get { return new RenameBuilder(_context, _sqlSyntax, _databaseProviders); }
}
public IUpdateBuilder Update
{
get { return new UpdateBuilder(_context, _databaseProviders); }
get { return new UpdateBuilder(_context, _sqlSyntax, _databaseProviders); }
}
}
}
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Text;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.SqlSyntax;
@@ -8,56 +9,76 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Insert.Expressions
public class InsertDataExpression : MigrationExpressionBase
{
private readonly List<InsertionDataDefinition> _rows = new List<InsertionDataDefinition>();
public InsertDataExpression()
{
}
public InsertDataExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders) : base(current, databaseProviders)
public InsertDataExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders, ISqlSyntaxProvider sqlSyntax)
: base(current, databaseProviders, sqlSyntax)
{
}
public string SchemaName { get; set; }
public string TableName { get; set; }
public bool EnabledIdentityInsert { get; set; }
public List<InsertionDataDefinition> Rows
{
get { return _rows; }
}
public override string ToString()
{
//TODO: This works for single insertion entries, not sure if it is valid for bulk insert operations!!!
if (IsExpressionSupported() == false)
return string.Empty;
var insertItems = new List<string>();
foreach (var item in Rows)
var sb = new StringBuilder();
if (EnabledIdentityInsert && SqlSyntax.SupportsIdentityInsert())
{
var cols = "";
var vals = "";
foreach (var keyVal in item)
sb.AppendLine(string.Format("SET IDENTITY_INSERT {0} ON;", SqlSyntax.GetQuotedTableName(TableName)));
if (CurrentDatabaseProvider == DatabaseProviders.SqlServer || CurrentDatabaseProvider == DatabaseProviders.SqlServerCE)
{
cols += keyVal.Key + ",";
vals += GetQuotedValue(keyVal.Value) + ",";
sb.AppendLine("GO");
}
cols = cols.TrimEnd(',');
vals = vals.TrimEnd(',');
var sql = string.Format(SqlSyntaxContext.SqlSyntaxProvider.InsertData,
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(TableName),
cols, vals);
insertItems.Add(sql);
}
return string.Join(",", insertItems);
try
{
foreach (var item in Rows)
{
var cols = "";
var vals = "";
foreach (var keyVal in item)
{
cols += SqlSyntax.GetQuotedColumnName(keyVal.Key) + ",";
vals += GetQuotedValue(keyVal.Value) + ",";
}
cols = cols.TrimEnd(',');
vals = vals.TrimEnd(',');
var sql = string.Format(SqlSyntax.InsertData,
SqlSyntax.GetQuotedTableName(TableName),
cols, vals);
sb.AppendLine(string.Format("{0};", sql));
if (CurrentDatabaseProvider == DatabaseProviders.SqlServer || CurrentDatabaseProvider == DatabaseProviders.SqlServerCE)
{
sb.AppendLine("GO");
}
}
}
finally
{
if (EnabledIdentityInsert && SqlSyntax.SupportsIdentityInsert())
{
sb.AppendLine(string.Format("SET IDENTITY_INSERT {0} OFF;", SqlSyntax.GetQuotedTableName(TableName)));
if (CurrentDatabaseProvider == DatabaseProviders.SqlServer || CurrentDatabaseProvider == DatabaseProviders.SqlServerCE)
{
sb.AppendLine("GO");
}
}
}
return sb.ToString();
}
@@ -2,6 +2,7 @@
{
public interface IInsertDataSyntax : IFluentSyntax
{
IInsertDataSyntax EnableIdentityInsert();
IInsertDataSyntax Row(object dataAsAnonymousType);
}
}
@@ -1,19 +1,24 @@
using Umbraco.Core.Persistence.Migrations.Syntax.Insert.Expressions;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Syntax.Insert
{
public class InsertBuilder : IInsertBuilder
{
private readonly IMigrationContext _context;
private readonly ISqlSyntaxProvider _sqlSyntax;
private readonly DatabaseProviders[] _databaseProviders;
public InsertBuilder(IMigrationContext context)
public InsertBuilder(IMigrationContext context, ISqlSyntaxProvider sqlSyntax, params DatabaseProviders[] databaseProviders)
{
_context = context;
_sqlSyntax = sqlSyntax;
_databaseProviders = databaseProviders;
}
public IInsertDataSyntax IntoTable(string tableName)
{
var expression = new InsertDataExpression { TableName = tableName };
var expression = new InsertDataExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax) { TableName = tableName };
_context.Expressions.Add(expression);
return new InsertDataBuilder(expression);
}
@@ -14,6 +14,12 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Insert
_expression = expression;
}
public IInsertDataSyntax EnableIdentityInsert()
{
_expression.EnabledIdentityInsert = true;
return this;
}
public IInsertDataSyntax Row(object dataAsAnonymousType)
{
_expression.Rows.Add(GetData(dataAsAnonymousType));
@@ -3,13 +3,9 @@
namespace Umbraco.Core.Persistence.Migrations.Syntax.Rename.Expressions
{
public class RenameColumnExpression : MigrationExpressionBase
{
public RenameColumnExpression()
{
}
public RenameColumnExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders)
: base(current, databaseProviders)
{
public RenameColumnExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders, ISqlSyntaxProvider sqlSyntax)
: base(current, databaseProviders, sqlSyntax)
{
}
@@ -52,7 +48,7 @@ SELECT CONCAT(
if (IsExpressionSupported() == false)
return string.Empty;
return SqlSyntaxContext.SqlSyntaxProvider.FormatColumnRename(TableName, OldName, NewName);
return SqlSyntax.FormatColumnRename(TableName, OldName, NewName);
}
}
}
@@ -4,12 +4,8 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Rename.Expressions
{
public class RenameTableExpression : MigrationExpressionBase
{
public RenameTableExpression()
{
}
public RenameTableExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders)
: base(current, databaseProviders)
public RenameTableExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders, ISqlSyntaxProvider sqlSyntax)
: base(current, databaseProviders, sqlSyntax)
{
}
@@ -22,7 +18,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Rename.Expressions
if (IsExpressionSupported() == false)
return string.Empty;
return SqlSyntaxContext.SqlSyntaxProvider.FormatTableRename(OldName, NewName);
return SqlSyntax.FormatTableRename(OldName, NewName);
}
}
}
@@ -1,34 +1,33 @@
using Umbraco.Core.Persistence.Migrations.Syntax.Rename.Column;
using Umbraco.Core.Persistence.Migrations.Syntax.Rename.Expressions;
using Umbraco.Core.Persistence.Migrations.Syntax.Rename.Table;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Syntax.Rename
{
public class RenameBuilder : IRenameBuilder
{
private readonly IMigrationContext _context;
private readonly ISqlSyntaxProvider _sqlSyntax;
private readonly DatabaseProviders[] _databaseProviders;
public RenameBuilder(IMigrationContext context, params DatabaseProviders[] databaseProviders)
public RenameBuilder(IMigrationContext context, ISqlSyntaxProvider sqlSyntax, params DatabaseProviders[] databaseProviders)
{
_context = context;
_sqlSyntax = sqlSyntax;
_databaseProviders = databaseProviders;
}
public IRenameTableSyntax Table(string oldName)
{
var expression = _databaseProviders == null
? new RenameTableExpression {OldName = oldName}
: new RenameTableExpression(_context.CurrentDatabaseProvider, _databaseProviders) { OldName = oldName };
var expression = new RenameTableExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax) { OldName = oldName };
_context.Expressions.Add(expression);
return new RenameTableBuilder(expression);
}
public IRenameColumnTableSyntax Column(string oldName)
{
var expression = _databaseProviders == null
? new RenameColumnExpression {OldName = oldName}
: new RenameColumnExpression(_context.CurrentDatabaseProvider, _databaseProviders) { OldName = oldName };
var expression = new RenameColumnExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax) { OldName = oldName };
_context.Expressions.Add(expression);
return new RenameColumnBuilder(expression);
}
@@ -5,11 +5,8 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Update.Expressions
{
public class UpdateDataExpression : MigrationExpressionBase
{
public UpdateDataExpression()
{
}
public UpdateDataExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders) : base(current, databaseProviders)
public UpdateDataExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders, ISqlSyntaxProvider sqlSyntax)
: base(current, databaseProviders, sqlSyntax)
{
}
@@ -31,7 +28,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Update.Expressions
foreach (var item in Set)
{
updateItems.Add(string.Format("{0} = {1}",
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName(item.Key),
SqlSyntax.GetQuotedColumnName(item.Key),
GetQuotedValue(item.Value)));
}
@@ -44,13 +41,13 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Update.Expressions
foreach (var item in Where)
{
whereClauses.Add(string.Format("{0} {1} {2}",
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName(item.Key),
SqlSyntax.GetQuotedColumnName(item.Key),
item.Value == null ? "IS" : "=",
GetQuotedValue(item.Value)));
}
}
return string.Format(SqlSyntaxContext.SqlSyntaxProvider.UpdateData,
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(TableName),
return string.Format(SqlSyntax.UpdateData,
SqlSyntax.GetQuotedTableName(TableName),
string.Join(", ", updateItems.ToArray()),
string.Join(" AND ", whereClauses.ToArray()));
}
@@ -1,23 +1,24 @@
using Umbraco.Core.Persistence.Migrations.Syntax.Update.Expressions;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Syntax.Update
{
public class UpdateBuilder : IUpdateBuilder
{
private readonly IMigrationContext _context;
private readonly ISqlSyntaxProvider _sqlSyntax;
private readonly DatabaseProviders[] _databaseProviders;
public UpdateBuilder(IMigrationContext context, params DatabaseProviders[] databaseProviders)
public UpdateBuilder(IMigrationContext context, ISqlSyntaxProvider sqlSyntax, params DatabaseProviders[] databaseProviders)
{
_context = context;
_sqlSyntax = sqlSyntax;
_databaseProviders = databaseProviders;
}
public IUpdateSetSyntax Table(string tableName)
{
var expression = _databaseProviders == null
? new UpdateDataExpression { TableName = tableName }
: new UpdateDataExpression(_context.CurrentDatabaseProvider, _databaseProviders) { TableName = tableName };
var expression = new UpdateDataExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax) { TableName = tableName };
_context.Expressions.Add(expression);
return new UpdateDataBuilder(expression, _context);
}
@@ -3,6 +3,7 @@ using System.CodeDom;
using System.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.SqlSyntax;
@@ -14,12 +15,12 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
[Migration("7.0.0", 4, GlobalSettings.UmbracoMigrationName)]
public class AddIndexToCmsMacroTable : MigrationBase
{
private readonly bool _skipIndexCheck;
private readonly bool _forTesting;
internal AddIndexToCmsMacroTable(bool skipIndexCheck, ISqlSyntaxProvider sqlSyntax, ILogger logger)
internal AddIndexToCmsMacroTable(bool forTesting, ISqlSyntaxProvider sqlSyntax, ILogger logger)
: base(sqlSyntax, logger)
{
_skipIndexCheck = skipIndexCheck;
_forTesting = forTesting;
}
public AddIndexToCmsMacroTable(ISqlSyntaxProvider sqlSyntax, ILogger logger) : base(sqlSyntax, logger)
@@ -28,7 +29,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
public override void Up()
{
var dbIndexes = _skipIndexCheck ? new DbIndexDefinition[] { } : SqlSyntax.GetDefinedIndexes(Context.Database)
var dbIndexes = _forTesting ? new DbIndexDefinition[] { } : SqlSyntax.GetDefinedIndexes(Context.Database)
.Select(x => new DbIndexDefinition()
{
TableName = x.Item1,
@@ -40,6 +41,30 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
//make sure it doesn't already exist
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsMacro_Alias")) == false)
{
//in order to create this index, we need to ensure that there are no duplicates. This could have happened with very old/corrupt umbraco versions.
// So we'll remove any duplicates based on alias and only keep the one with the smallest id since I'm pretty sure we'd always choose the 'first' one
// when running a query.
if (_forTesting == false)
{
//NOTE: Using full SQL statement here in case the DTO has changed between versions
var macros = Context.Database.Fetch<MacroDto>("SELECT * FROM cmsMacro")
.GroupBy(x => x.Alias)
.Where(x => x.Count() > 1);
foreach (var m in macros)
{
//get the min id (to keep)
var minId = m.Min(x => x.Id);
//delete all the others
foreach (var macroDto in m.Where(x => x.Id != minId))
{
Delete.FromTable("cmsMacro").Row(new { id = macroDto.Id });
}
}
}
Create.Index("IX_cmsMacro_Alias").OnTable("cmsMacro").OnColumn("macroAlias").Unique();
}
@@ -27,6 +27,11 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
}).ToArray();
//add a foreign key to the parent id column too!
//In some cases in very old corrupted db's this will fail, so it means we need to clean the data first
//set the parentID to NULL where it doesn't actually exist in the normal ids
Execute.Sql(@"UPDATE cmsTags SET parentId = NULL WHERE parentId IS NOT NULL AND parentId NOT IN (SELECT id FROM cmsTags)");
Create.ForeignKey("FK_cmsTags_cmsTags")
.FromTable("cmsTags")
.ForeignColumn("ParentId")
@@ -55,9 +55,11 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
}
var propertyTypeIds = propertyData.Select(x => x.PropertyTypeId).Distinct();
var propertyTypes = database.Fetch<PropertyTypeDto>(
"WHERE id in (@propertyTypeIds)", new { propertyTypeIds = propertyTypeIds });
//NOTE: We are writing the full query because we've added a column to the PropertyTypeDto in later versions so one of the columns
// won't exist yet
var propertyTypes = database.Fetch<PropertyTypeDto>("SELECT * FROM cmsPropertyType WHERE id in (@propertyTypeIds)", new { propertyTypeIds = propertyTypeIds });
foreach (var data in propertyData)
{
if (string.IsNullOrEmpty(data.Text) == false)
@@ -3,6 +3,8 @@ using System.Data;
using System.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZero
@@ -30,6 +32,53 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
Delete.FromTable("cmsLanguageText").Row(new { pk = pk });
}
var columns = SqlSyntax.GetColumnsInSchema(Context.Database).Distinct().ToArray();
if (columns.Any(x => x.ColumnName.InvariantEquals("id")
&& x.TableName.InvariantEquals("umbracoLanguage")
&& x.DataType.InvariantEquals("smallint")))
{
//Ensure that the umbracoLanguage PK is INT and not SmallInt (which it might be in older db versions)
// In order to 'change' this to an INT, we have to run a full migration script which is super annoying
Create.Table("umbracoLanguage_TEMP")
.WithColumn("id").AsInt32().NotNullable().Identity()
.WithColumn("languageISOCode").AsString(10).Nullable()
.WithColumn("languageCultureName").AsString(50).Nullable();
var currentData = this.Context.Database.Fetch<LanguageDto>(new Sql().Select("*").From<LanguageDto>(SqlSyntax));
foreach (var languageDto in currentData)
{
Insert.IntoTable("umbracoLanguage_TEMP")
.EnableIdentityInsert()
.Row(new {id = languageDto.Id, languageISOCode = languageDto.IsoCode, languageCultureName = languageDto.CultureName});
}
//ok, all data has been copied over, drop the old table, rename the temp table and re-add constraints.
Delete.Table("umbracoLanguage");
Rename.Table("umbracoLanguage_TEMP").To("umbracoLanguage");
//add the pk
Create.PrimaryKey("PK_language").OnTable("umbracoLanguage").Column("id");
}
var dbIndexes = SqlSyntax.GetDefinedIndexes(Context.Database)
.Select(x => new DbIndexDefinition
{
TableName = x.Item1,
IndexName = x.Item2,
ColumnName = x.Item3,
IsUnique = x.Item4
}).ToArray();
//make sure it doesn't already exist
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsDictionary_id")) == false)
{
Create.Index("IX_cmsDictionary_id").OnTable("cmsDictionary")
.OnColumn("id").Ascending()
.WithOptions().NonClustered()
.WithOptions().Unique();
}
//now we need to create a foreign key
Create.ForeignKey("FK_cmsLanguageText_umbracoLanguage_id").FromTable("cmsLanguageText").ForeignColumn("languageId")
.ToTable("umbracoLanguage").PrimaryColumn("id").OnDeleteOrUpdate(Rule.None);
@@ -52,7 +101,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
public override void Down()
{
throw new System.NotImplementedException();
throw new NotImplementedException();
}
}
}
@@ -0,0 +1,58 @@
using System;
using System.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZero
{
[Migration("7.3.0", 17, GlobalSettings.UmbracoMigrationName)]
public class AddServerRegistrationColumnsAndLock : MigrationBase
{
public AddServerRegistrationColumnsAndLock(ISqlSyntaxProvider sqlSyntax, ILogger logger)
: base(sqlSyntax, logger)
{ }
public override void Up()
{
// don't execute if the column is already there
var columns = SqlSyntax.GetColumnsInSchema(Context.Database).ToArray();
if (columns.Any(x => x.TableName.InvariantEquals("umbracoServer") && x.ColumnName.InvariantEquals("isMaster")) == false)
{
Create.Column("isMaster").OnTable("umbracoServer").AsBoolean().NotNullable().WithDefaultValue(0);
}
EnsureLockObject(Constants.System.ServersLock, "0AF5E610-A310-4B6F-925F-E928D5416AF7", "LOCK: Servers");
}
public override void Down()
{
// not implemented
}
private void EnsureLockObject(int id, string uniqueId, string text)
{
var exists = Context.Database.Exists<NodeDto>(id);
if (exists) return;
Insert
.IntoTable("umbracoNode")
.EnableIdentityInsert()
.Row(new
{
id = id, // NodeId
trashed = false,
parentId = -1,
nodeUser = 0,
level = 1,
path = "-1," + id,
sortOrder = 0,
uniqueId = new Guid(uniqueId),
text = text,
nodeObjectType = new Guid(Constants.ObjectTypes.LockObject),
createDate = DateTime.Now
});
}
}
}
@@ -6,6 +6,7 @@ using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZero
{
[Migration("7.3.0", 13, GlobalSettings.UmbracoMigrationName)]
public class AddUniqueIdPropertyTypeColumn : MigrationBase
{
@@ -35,13 +36,17 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
// the already existing data, see: http://issues.umbraco.org/issue/U4-6942
foreach (var data in Context.Database.Query<dynamic>(@"
SELECT cmsPropertyType.id ptId, cmsPropertyType.Alias ptAlias, cmsContentType.alias ctAlias
SELECT cmsPropertyType.id ptId, cmsPropertyType.Alias ptAlias, cmsContentType.alias ctAlias, umbracoNode.nodeObjectType nObjType
FROM cmsPropertyType
INNER JOIN cmsContentType
ON cmsPropertyType.contentTypeId = cmsContentType.nodeId"))
ON cmsPropertyType.contentTypeId = cmsContentType.nodeId
INNER JOIN umbracoNode
ON cmsContentType.nodeId = umbracoNode.id"))
{
//create a guid from the concatenation of the property type alias + the doc type alias
string concatAlias = data.ptAlias + data.ctAlias;
//create a guid from the concatenation of the:
// property type alias + the doc type alias + the content type node object type
// - the latter is required because there can be a content type and media type with the same alias!!
string concatAlias = data.ptAlias + data.ctAlias + data.nObjType;
var ptGuid = concatAlias.ToGuid();
//set the Unique Id to the one we've generated
@@ -0,0 +1,49 @@
using System.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZero
{
/// <summary>
/// Older corrupted dbs might have multiple published flags for a content item, this shouldn't be possible
/// so we need to clear the content flag on the older version
/// </summary>
[Migration("7.3.0", 18, GlobalSettings.UmbracoMigrationName)]
public class CleanUpCorruptedPublishedFlags : MigrationBase
{
public CleanUpCorruptedPublishedFlags(ISqlSyntaxProvider sqlSyntax, ILogger logger)
: base(sqlSyntax, logger)
{
}
public override void Up()
{
//Get all cmsDocument items that have more than one published date set
var sql = @"SELECT * FROM cmsDocument WHERE nodeId IN
(SELECT nodeId
FROM cmsDocument
GROUP BY nodeId
HAVING SUM(CASE WHEN published = 0 THEN 0 ELSE 1 END) > 1)
AND published = 1
ORDER BY nodeId, updateDate";
var docs = Context.Database.Fetch<DocumentDto>(sql).GroupBy(x => x.NodeId);
foreach (var doc in docs)
{
var latest = doc.OrderByDescending(x => x.UpdateDate).First();
foreach (var old in doc.Where(x => x.VersionId != latest.VersionId))
{
Update.Table("cmsDocument").Set(new {published = 0}).Where(new {nodeId = old.NodeId});
}
}
}
public override void Down()
{
}
}
}
@@ -28,14 +28,11 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
var textType = SqlSyntax.GetSpecialDbType(SpecialDbTypes.NTEXT);
Create.Table("umbracoCacheInstruction")
.WithColumn("id").AsInt32().Identity().NotNullable()
.WithColumn("id").AsInt32().NotNullable().PrimaryKey("PK_umbracoCacheInstruction").Identity()
.WithColumn("utcStamp").AsDateTime().NotNullable()
.WithColumn("jsonInstruction").AsCustom(textType).NotNullable()
.WithColumn("originated").AsString(500).NotNullable();
Create.PrimaryKey("PK_umbracoCacheInstruction")
.OnTable("umbracoCacheInstruction")
.Column("id");
}
public override void Down()
@@ -3,6 +3,7 @@ using System.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZero
@@ -23,34 +24,92 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
{
//Don't execute anything if there is no 'master' column - this might occur if the db is already upgraded
var cols = SqlSyntax.GetColumnsInSchema(Context.Database);
var cols = SqlSyntax.GetColumnsInSchema(Context.Database).ToArray();
if (cols.Any(x => x.ColumnName.InvariantEquals("master") && x.TableName.InvariantEquals("cmsTemplate")) == false)
{
return;
}
var constraints = SqlSyntax.GetConstraintsPerColumn(Context.Database).Distinct().ToArray();
//update the parentId column for all templates to be correct so it matches the current 'master' template
//NOTE: we are using dynamic because we need to get the data in a column that no longer exists in the schema
var templates = Context.Database.Fetch<dynamic>(new Sql().Select("*").From<TemplateDto>());
foreach (var template in templates)
{
Update.Table("umbracoNode").Set(new {parentID = template.master ?? -1}).Where(new {id = template.nodeId});
//now build the correct path for the template
Update.Table("umbracoNode").Set(new { path = BuildPath (template, templates)}).Where(new { id = template.nodeId });
}
//In some old corrupted databases, the information will not be correct in the master column so we need to fix that
//first by nulling out the master column where the id doesn't actually exist
Execute.Sql(@"UPDATE cmsTemplate SET master = NULL WHERE " +
SqlSyntax.GetQuotedColumnName("master") + @" IS NOT NULL AND " +
SqlSyntax.GetQuotedColumnName("master") + @" NOT IN (" +
//Stupid MySQL... needs this stupid syntax because it can do an update with a sub query of itself,
// yet it can do one with a sub sub query
// ... this will work in all dbs too
@"SELECT nodeId FROM (SELECT * FROM cmsTemplate a) b)");
//Now we can bulk update the parentId column
//NOTE: This single statement should be used but stupid SQLCE doesn't support Update with a FROM !!
// so now we have to do this by individual rows :(
//Execute.Sql(@"UPDATE umbracoNode
//SET parentID = COALESCE(t2." + SqlSyntax.GetQuotedColumnName("master") + @", -1)
//FROM umbracoNode t1
//INNER JOIN cmsTemplate t2
//ON t1.id = t2.nodeId");
Execute.Code(database =>
{
var templateData = database.Fetch<dynamic>("SELECT * FROM cmsTemplate");
foreach (var template in templateData)
{
var sql = "SET parentID=@parentId WHERE id=@nodeId";
LogHelper.Info<MigrateAndRemoveTemplateMasterColumn>("Executing sql statement: UPDATE umbracoNode " + sql);
database.Update<NodeDto>(sql,
new {parentId = template.master ?? -1, nodeId = template.nodeId});
}
return string.Empty;
});
//Now we can update the path, but this needs to be done in a delegate callback so that the query runs after the updates just completed
Execute.Code(database =>
{
//NOTE: we are using dynamic because we need to get the data in a column that no longer exists in the schema
var templates = database.Fetch<dynamic>(new Sql().Select("*").From<TemplateDto>());
foreach (var template in templates)
{
var sql = string.Format(SqlSyntax.UpdateData,
SqlSyntax.GetQuotedTableName("umbracoNode"),
"path=@buildPath",
"id=@nodeId");
LogHelper.Info<MigrateAndRemoveTemplateMasterColumn>("Executing sql statement: " + sql);
//now build the correct path for the template
database.Execute(sql, new
{
buildPath = BuildPath(template, templates),
nodeId = template.nodeId
});
}
return string.Empty;
});
//now remove the master column and key
if (this.Context.CurrentDatabaseProvider == DatabaseProviders.MySql)
{
Delete.ForeignKey().FromTable("cmsTemplate").ForeignColumn("master").ToTable("umbracoUser").PrimaryColumn("id");
//Because MySQL doesn't name keys with what you want, we need to query for the one that is associated
// this is required for this specific case because there are 2 foreign keys on the cmsTemplate table
var fkName = constraints.FirstOrDefault(x => x.Item1.InvariantEquals("cmsTemplate") && x.Item2.InvariantEquals("master"));
if (fkName != null)
{
Delete.ForeignKey(fkName.Item3).OnTable("cmsTemplate");
}
}
else
{
//These are the old aliases, before removing them, check they exist
var constraints = SqlSyntax.GetConstraintsPerColumn(Context.Database).Distinct().ToArray();
if (constraints.Any(x => x.Item1.InvariantEquals("cmsTemplate") && x.Item3.InvariantEquals("FK_cmsTemplate_cmsTemplate")))
{
Delete.ForeignKey("FK_cmsTemplate_cmsTemplate").OnTable("cmsTemplate");
@@ -59,8 +118,24 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
//TODO: Hopefully it's not named something else silly in some crazy old versions
}
var columns = SqlSyntax.GetColumnsInSchema(Context.Database).Distinct().ToArray();
if (columns.Any(x => x.ColumnName.InvariantEquals("master") && x.TableName.InvariantEquals("cmsTemplate")))
var dbIndexes = SqlSyntax.GetDefinedIndexes(Context.Database)
.Select(x => new DbIndexDefinition()
{
TableName = x.Item1,
IndexName = x.Item2,
ColumnName = x.Item3,
IsUnique = x.Item4
}).ToArray();
//in some databases there's an index (IX_Master) on the master column which needs to be dropped first
var foundIndex = dbIndexes.FirstOrDefault(x => x.TableName.InvariantEquals("cmsTemplate") && x.ColumnName.InvariantEquals("master"));
if (foundIndex != null)
{
Delete.Index(foundIndex.IndexName).OnTable("cmsTemplate");
}
if (cols.Any(x => x.ColumnName.InvariantEquals("master") && x.TableName.InvariantEquals("cmsTemplate")))
{
Delete.Column("master").FromTable("cmsTemplate");
}
@@ -28,8 +28,11 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixZeroOne
{
if (database != null)
{
//Fetch all PropertyTypes that belongs to a PropertyTypeGroup
var propertyTypes = database.Fetch<PropertyTypeDto>("WHERE propertyTypeGroupId > 0");
//Fetch all PropertyTypes that belongs to a PropertyTypeGroup
//NOTE: We are writing the full query because we've added a column to the PropertyTypeDto in later versions so one of the columns
// won't exist yet
var propertyTypes = database.Fetch<PropertyTypeDto>("SELECT * FROM cmsPropertyType WHERE propertyTypeGroupId > 0");
var propertyGroups = database.Fetch<PropertyTypeGroupDto>("WHERE id > 0");
foreach (var propertyType in propertyTypes)
+79 -15
View File
@@ -215,6 +215,10 @@ namespace Umbraco.Core.Persistence
_paramPrefix = "?";
if (_dbType == DBType.Oracle)
_paramPrefix = ":";
// by default use MSSQL default ReadCommitted level
//TODO change to RepeatableRead - but that is breaking
_isolationLevel = IsolationLevel.ReadCommitted;
}
// Automatically close one open shared connection
@@ -237,7 +241,27 @@ namespace Umbraco.Core.Persistence
_sharedConnection.ConnectionString = _connectionString;
_sharedConnection.OpenWithRetry();//Changed .Open() => .OpenWithRetry() extension method
_sharedConnection = OnConnectionOpened(_sharedConnection);
// ensure we have the proper isolation level, as levels can leak in pools
// read http://stackoverflow.com/questions/9851415/sql-server-isolation-level-leaks-across-pooled-connections
// and http://stackoverflow.com/questions/641120/what-exec-sp-reset-connection-shown-in-sql-profiler-means
//
// NPoco has that code in OpenSharedConnectionImp (commented out?)
//using (var cmd = _sharedConnection.CreateCommand())
//{
// cmd.CommandText = GetSqlForTransactionLevel(_isolationLevel);
// cmd.CommandTimeout = CommandTimeout;
// cmd.ExecuteNonQuery();
//}
//
// although MSDN documentation for SQL CE clearly states that the above method
// should work, it fails & reports an error parsing the query on 'TRANSACTION',
// and Google is no help (others have faced the same issue... no solution). So,
// switching to another method that does work on all databases.
var tr = _sharedConnection.BeginTransaction(_isolationLevel);
tr.Commit();
tr.Dispose();
_sharedConnection = OnConnectionOpened(_sharedConnection);
if (KeepConnectionAlive)
_sharedConnectionDepth++; // Make sure you call Dispose
@@ -269,10 +293,20 @@ namespace Umbraco.Core.Persistence
// Helper to create a transaction scope
public Transaction GetTransaction()
{
return new Transaction(this);
}
return GetTransaction(_isolationLevel);
}
// Use by derived repo generated by T4 templates
public Transaction GetTransaction(IsolationLevel isolationLevel)
{
return new Transaction(this, isolationLevel);
}
public IsolationLevel CurrentTransactionIsolationLevel
{
get { return _transaction == null ? IsolationLevel.Unspecified : _transaction.IsolationLevel; }
}
// Use by derived repo generated by T4 templates
public virtual void OnBeginTransaction() { }
public virtual void OnEndTransaction() { }
@@ -281,17 +315,23 @@ namespace Umbraco.Core.Persistence
// Use `using (var scope=db.Transaction) { scope.Complete(); }` to ensure correct semantics
public void BeginTransaction()
{
_transactionDepth++;
BeginTransaction(_isolationLevel);
}
public void BeginTransaction(IsolationLevel isolationLevel)
{
_transactionDepth++;
if (_transactionDepth == 1)
{
OpenSharedConnection();
_transaction = _sharedConnection.BeginTransaction();
_transaction = _sharedConnection.BeginTransaction(isolationLevel);
_transactionCancelled = false;
OnBeginTransaction();
}
}
else if (isolationLevel > _transaction.IsolationLevel)
throw new Exception("Already in a transaction with a lower isolation level.");
}
// Internal helper to cleanup transaction stuff
void CleanupTransaction()
@@ -313,6 +353,7 @@ namespace Umbraco.Core.Persistence
public void AbortTransaction()
{
_transactionCancelled = true;
//TODO what shall we do if transactionDepth is already zero?
if ((--_transactionDepth) == 0)
CleanupTransaction();
}
@@ -320,11 +361,32 @@ namespace Umbraco.Core.Persistence
// Complete the transaction
public void CompleteTransaction()
{
if ((--_transactionDepth) == 0)
//TODO what shall we do if transactionDepth is already zero?
if ((--_transactionDepth) == 0)
CleanupTransaction();
}
// Helper to handle named parameters from object properties
// in NPoco this is in DatabaseType
private static string GetSqlForTransactionLevel(IsolationLevel isolationLevel)
{
switch (isolationLevel)
{
case IsolationLevel.ReadCommitted:
return "SET TRANSACTION ISOLATION LEVEL READ COMMITTED";
case IsolationLevel.ReadUncommitted:
return "SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED";
case IsolationLevel.RepeatableRead:
return "SET TRANSACTION ISOLATION LEVEL REPEATABLE READ";
case IsolationLevel.Serializable:
return "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE";
case IsolationLevel.Snapshot:
return "SET TRANSACTION ISOLATION LEVEL SNAPSHOT";
default:
return "SET TRANSACTION ISOLATION LEVEL READ COMMITTED";
}
}
// Helper to handle named parameters from object properties
static Regex rxParams = new Regex(@"(?<!@)@\w+", RegexOptions.Compiled);
public static string ProcessParams(string _sql, object[] args_src, List<object> args_dest)
{
@@ -2264,16 +2326,17 @@ namespace Umbraco.Core.Persistence
string _lastSql;
object[] _lastArgs;
string _paramPrefix = "@";
IsolationLevel _isolationLevel;
}
// Transaction object helps maintain transaction depth counts
public class Transaction : IDisposable
{
public Transaction(Database db)
{
_db = db;
_db.BeginTransaction();
}
public Transaction(Database db, IsolationLevel isolationLevel)
{
_db = db;
_db.BeginTransaction(isolationLevel);
}
public virtual void Complete()
{
@@ -2283,6 +2346,7 @@ namespace Umbraco.Core.Persistence
public void Dispose()
{
//TODO prevent multiple calls to Dispose
if (_db != null)
_db.AbortTransaction();
}
@@ -1070,6 +1070,11 @@ AND umbracoNode.id <> @id",
out IDictionary<int, PropertyTypeCollection> allPropertyTypeCollection,
out IDictionary<int, PropertyGroupCollection> allPropertyGroupCollection)
{
allPropertyGroupCollection = new Dictionary<int, PropertyGroupCollection>();
allPropertyTypeCollection = new Dictionary<int, PropertyTypeCollection>();
// query below is not safe + pointless if array is empty
if (contentTypeIds.Length == 0) return;
// first part Gets all property groups including property type data even when no property type exists on the group
// second part Gets all property types including ones that are not on a group
@@ -1105,10 +1110,8 @@ AND umbracoNode.id <> @id",
INNER JOIN cmsDataType as DT
ON PT.dataTypeId = DT.nodeId
LEFT JOIN cmsPropertyTypeGroup as PG
ON PG.id = PT.propertyTypeGroupId");
if (contentTypeIds.Any())
sqlBuilder.AppendLine(" WHERE (PT.contentTypeId in (@contentTypeIds))");
ON PG.id = PT.propertyTypeGroupId
WHERE (PT.contentTypeId in (@contentTypeIds))");
sqlBuilder.AppendLine(" ORDER BY (pgId)");
@@ -1119,9 +1122,6 @@ AND umbracoNode.id <> @id",
var result = db.Fetch<dynamic>(sqlBuilder.ToString(), new { contentTypeIds = contentTypeIds });
allPropertyGroupCollection = new Dictionary<int, PropertyGroupCollection>();
allPropertyTypeCollection = new Dictionary<int, PropertyTypeCollection>();
foreach (var contentTypeId in contentTypeIds)
{
//from this we need to make :
@@ -79,7 +79,7 @@ namespace Umbraco.Core.Persistence.Repositories
public object GetCacheItem(string cacheKey, Func<object> getCacheItem)
{
return InnerProvider.GetCacheItem(cacheKey, () =>
var cached = InnerProvider.GetCacheItem(cacheKey, () =>
{
var result = DictionaryCacheProviderBase.GetSafeLazy(getCacheItem);
var value = result.Value; // force evaluation now - this may throw if cacheItem throws, and then nothing goes into cache
@@ -87,18 +87,21 @@ namespace Umbraco.Core.Persistence.Repositories
return CheckCloneableAndTracksChanges(value);
});
return CheckCloneableAndTracksChanges(cached);
}
public object GetCacheItem(string cacheKey, Func<object> getCacheItem, TimeSpan? timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
{
return InnerProvider.GetCacheItem(cacheKey, () =>
var cached = InnerProvider.GetCacheItem(cacheKey, () =>
{
var result = DictionaryCacheProviderBase.GetSafeLazy(getCacheItem);
var value = result.Value; // force evaluation now - this may throw if cacheItem throws, and then nothing goes into cache
if (value == null) return null; // do not store null values (backward compat)
return CheckCloneableAndTracksChanges(value);
}, timeout, isSliding, priority, removedCallback, dependentFiles);
}, timeout, isSliding, priority, removedCallback, dependentFiles);
return CheckCloneableAndTracksChanges(cached);
}
public void InsertCacheItem(string cacheKey, Func<object> getCacheItem, TimeSpan? timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
@@ -307,7 +307,7 @@ namespace Umbraco.Core.Persistence.Repositories
.Append(new Sql(") tmpTbl LEFT JOIN ("))
.Append(joinSql)
.Append(new Sql(") as property ON id = property.contentNodeId"))
.OrderBy("sortOrder");
.OrderBy("sortOrder, id");
return wrappedSql;
}

Some files were not shown because too many files have changed in this diff Show More