├── .gitattributes
├── .github
└── ISSUE_TEMPLATE
│ └── default.md
├── .gitignore
├── DacFxStronglyTypedModel
├── DacFxStronglyTypedModel.csproj
├── ISqlModelElement.cs
├── ISqlModelElementReference.cs
├── Interfaces.cs
├── Interfaces.tt
├── MarkerInterfaces.cs
├── ModelExtensions.cs
├── ModelMessages.Designer.cs
├── ModelMessages.resx
├── ModelUtilityMethods.cs
├── ModelUtilityMethods.tt
├── Properties
│ └── AssemblyInfo.cs
├── TSqlModelElement.cs
├── TSqlModelElementReference.cs
├── TSqlTypedModel.cs
├── UnresolvedElementException.cs
├── Utils.cs
├── Utils.tt
├── VersionSpecificImplementations.cs
├── VersionSpecificImplementations.tt
├── model.cs
├── model.tt
├── modelmetadata.xml
└── packages.config
├── DacPublicSamples.sln
├── LICENSE
├── README.md
├── RuleSamples
├── AvoidWaitForDelayRule.cs
├── CapitalizedNamesRule.cs
├── InMemoryTableBin2CollationRule.cs
├── LocalizedExportCodeAnalysisRuleAttribute.cs
├── Properties
│ └── AssemblyInfo.cs
├── RuleConstants.cs
├── RuleResources.Designer.cs
├── RuleResources.resx
├── RuleSamples.csproj
├── RuleUtils.cs
├── TSqlScriptDomUtils.cs
├── TableNameEndingInViewRule.cs
├── ViewsOnMemoryOptimizedTableRule.cs
├── WaitForDelayVisitor.cs
└── packages.config
├── RuleTests
├── BaselinedRuleTest.cs
├── Properties
│ └── AssemblyInfo.cs
├── RuleTest.cs
├── RuleTestCases.cs
├── RuleTestUtils.cs
├── RuleTests.csproj
├── TestScripts
│ ├── AvoidWaitForDelayRule
│ │ ├── AvoidWaitForDelayRule-Baseline.txt
│ │ ├── DatabaseScalarFunction1.sql
│ │ ├── InlineFunction.sql
│ │ ├── ProcWithWaitForDelay.sql
│ │ ├── ProcWithWaitForTime.sql
│ │ ├── ServerTrigger1.sql
│ │ ├── Table1.sql
│ │ └── TableValuedFunctionWithWaitForDelay.sql
│ ├── README.txt
│ ├── TestBin2CollationOnProjectRule
│ │ ├── Filegroup.sql
│ │ ├── TableWithBin2Collation.sql
│ │ ├── TableWithSpecificNonBin2Collation.sql
│ │ ├── TableWithoutBin2Collation.sql
│ │ ├── TestBin2CollationOnProjectRule-Baseline.txt
│ │ └── UddtTests.sql
│ ├── TestCapitalizedNamesRule
│ │ ├── TestCapitalizedNamesRule-Baseline.txt
│ │ └── TestScript.sql
│ ├── TestNonBin2CollationOnProjectRule
│ │ ├── Filegroup.sql
│ │ ├── TableWithBin2Collation.sql
│ │ ├── TableWithSpecificNonBin2Collation.sql
│ │ ├── TableWithoutBin2Collation.sql
│ │ ├── TestNonBin2CollationOnProjectRule-Baseline.txt
│ │ └── UddtTests.sql
│ └── TestViewOnMemoryOptimizedTableRule
│ │ ├── Filegroup.sql
│ │ ├── Table1.sql
│ │ ├── Table2.sql
│ │ ├── TestViewOnMemoryOptimizedTableRule-Baseline.txt
│ │ └── View1Tests.sql
└── packages.config
├── SECURITY.md
├── SampleConsoleApp
├── App.config
├── ModelEndToEnd.cs
├── ModelFilterExample.cs
├── Program.cs
├── Properties
│ └── AssemblyInfo.cs
├── RunCodeAnalysisExample.cs
├── RunValidateQuerySemanticallyExample.cs
├── SampleConsoleApp.csproj
└── packages.config
├── SampleTests
├── Properties
│ └── AssemblyInfo.cs
├── SampleTests.csproj
├── StronglyTypedUnitTests.cs
├── TestCreateIndexOperationalPropsModifier.cs
├── TestDbLocationModifiers.cs
├── TestDeploymentStoppingContributor.cs
├── TestFiltering.cs
└── packages.config
├── Samples
├── CompositeFilter.cs
├── Contributors
│ ├── AlterTableAlterColumnOnlineModifier.cs
│ ├── CreateIndexOperationalPropsModifier.cs
│ ├── DbCreateDatabaseModifier.cs
│ ├── DbLocationModifier.cs
│ ├── DefaultConstraintNameModifier.cs
│ └── DeploymentStoppingContributor.cs
├── DisposableList.cs
├── Filter.cs
├── ModelFilterer.cs
├── PlanFilterer.cs
├── Properties
│ └── AssemblyInfo.cs
├── Samples.csproj
├── SchemaBasedFilter.cs
├── TSqlModelExtensions.cs
├── Utils.cs
└── packages.config
├── Scripts
└── RemoveMasterKey.ps1
└── TestUtils
├── CommonConstants.cs
├── ExceptionText.cs
├── InstanceInfo.cs
├── Properties
└── AssemblyInfo.cs
├── SqlTestDb.cs
├── TestUtils.cs
├── TestUtils.csproj
└── packages.config
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/default.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Default
3 | about: Default issue template
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 |
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.sln.docstates
8 |
9 | # Build results
10 |
11 | [Dd]ebug/
12 | [Rr]elease/
13 | x64/
14 | build/
15 | [Bb]in/
16 | [Oo]bj/
17 |
18 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
19 | !packages/*/build/
20 |
21 | # MSTest test Results
22 | [Tt]est[Rr]esult*/
23 | [Bb]uild[Ll]og.*
24 |
25 | *_i.c
26 | *_p.c
27 | *.ilk
28 | *.meta
29 | *.obj
30 | *.pch
31 | *.pdb
32 | *.pgc
33 | *.pgd
34 | *.rsp
35 | *.sbr
36 | *.tlb
37 | *.tli
38 | *.tlh
39 | *.tmp
40 | *.tmp_proj
41 | *.log
42 | *.vspscc
43 | *.vssscc
44 | .builds
45 | *.pidb
46 | *.log
47 | *.scc
48 |
49 | # Visual C++ cache files
50 | ipch/
51 | *.aps
52 | *.ncb
53 | *.opensdf
54 | *.sdf
55 | *.cachefile
56 |
57 | # Visual Studio profiler
58 | *.psess
59 | *.vsp
60 | *.vspx
61 |
62 | # Guidance Automation Toolkit
63 | *.gpState
64 |
65 | # ReSharper is a .NET coding add-in
66 | _ReSharper*/
67 | *.[Rr]e[Ss]harper
68 |
69 | # TeamCity is a build add-in
70 | _TeamCity*
71 |
72 | # DotCover is a Code Coverage Tool
73 | *.dotCover
74 |
75 | # NCrunch
76 | *.ncrunch*
77 | .*crunch*.local.xml
78 |
79 | # Installshield output folder
80 | [Ee]xpress/
81 |
82 | # DocProject is a documentation generator add-in
83 | DocProject/buildhelp/
84 | DocProject/Help/*.HxT
85 | DocProject/Help/*.HxC
86 | DocProject/Help/*.hhc
87 | DocProject/Help/*.hhk
88 | DocProject/Help/*.hhp
89 | DocProject/Help/Html2
90 | DocProject/Help/html
91 |
92 | # Click-Once directory
93 | publish/
94 |
95 | # Publish Web Output
96 | *.Publish.xml
97 |
98 | # NuGet Packages Directory
99 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line
100 | packages/
101 |
102 | # Windows Azure Build Output
103 | csx
104 | *.build.csdef
105 |
106 | # Windows Store app package directory
107 | AppPackages/
108 |
109 | # Others
110 | sql/
111 | *.Cache
112 | ClientBin/
113 | [Ss]tyle[Cc]op.*
114 | ~$*
115 | *~
116 | *.dbmdl
117 | *.[Pp]ublish.xml
118 | *.pfx
119 | *.publishsettings
120 |
121 | # RIA/Silverlight projects
122 | Generated_Code/
123 |
124 | # Backup & report files from converting an old project file to a newer
125 | # Visual Studio version. Backup files are not needed, because we have git ;-)
126 | _UpgradeReport_Files/
127 | Backup*/
128 | UpgradeLog*.XML
129 | UpgradeLog*.htm
130 |
131 | # SQL Server files
132 | App_Data/*.mdf
133 | App_Data/*.ldf
134 |
135 |
136 | #LightSwitch generated files
137 | GeneratedArtifacts/
138 | _Pvt_Extensions/
139 | ModelManifest.xml
140 |
141 | # =========================
142 | # Windows detritus
143 | # =========================
144 |
145 | # Windows image file caches
146 | Thumbs.db
147 | ehthumbs.db
148 |
149 | # Folder config file
150 | Desktop.ini
151 |
152 | # Recycle Bin used on file shares
153 | $RECYCLE.BIN/
154 |
155 | # Mac desktop service store files
156 | .DS_Store
157 | /DacFxStronglyTypedModel.zip
158 | /.vs
159 |
--------------------------------------------------------------------------------
/DacFxStronglyTypedModel/ISqlModelElement.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | //
4 | // The MIT License (MIT)
5 | //
6 | // Copyright (c) 2015 Microsoft
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 | //------------------------------------------------------------------------------
27 | namespace Microsoft.SqlServer.Dac.Extensions.Prototype
28 | {
29 | using System;
30 | using Microsoft.SqlServer.TransactSql.ScriptDom;
31 | using Microsoft.SqlServer.Dac.Model;
32 | using System.Collections.Generic;
33 | public interface ISqlModelElement
34 | {
35 | ObjectIdentifier Name { get; }
36 | TSqlObject Element { get; }
37 | TSqlScript GetAst();
38 | IEnumerable GetChildren();
39 | IEnumerable GetChildren(DacQueryScopes queryScopes);
40 | object GetMetadata(ModelMetadataClass metadata);
41 | T GetMetadata(ModelMetadataClass metadata);
42 | TSqlObject GetParent();
43 | TSqlObject GetParent(DacQueryScopes queryScopes);
44 | object GetProperty(ModelPropertyClass property);
45 | T GetProperty(ModelPropertyClass property);
46 | IEnumerable GetReferenced();
47 | IEnumerable GetReferenced(DacQueryScopes queryScopes);
48 | IEnumerable GetReferenced(ModelRelationshipClass relationshipType);
49 | IEnumerable GetReferenced(ModelRelationshipClass relationshipType, DacQueryScopes queryScopes);
50 | IEnumerable GetReferencedRelationshipInstances();
51 | IEnumerable GetReferencedRelationshipInstances(DacExternalQueryScopes queryScopes);
52 | IEnumerable GetReferencedRelationshipInstances(DacQueryScopes queryScopes);
53 | IEnumerable GetReferencedRelationshipInstances(ModelRelationshipClass relationshipType);
54 | IEnumerable GetReferencedRelationshipInstances(ModelRelationshipClass relationshipType, DacExternalQueryScopes queryScopes);
55 | IEnumerable GetReferencedRelationshipInstances(ModelRelationshipClass relationshipType, DacQueryScopes queryScopes);
56 | IEnumerable GetReferencing();
57 | IEnumerable GetReferencing(DacQueryScopes queryScopes);
58 | IEnumerable GetReferencing(ModelRelationshipClass relationshipType);
59 | IEnumerable GetReferencing(ModelRelationshipClass relationshipType, DacQueryScopes queryScopes);
60 | IEnumerable GetReferencingRelationshipInstances();
61 | IEnumerable GetReferencingRelationshipInstances(DacQueryScopes queryScopes);
62 | IEnumerable GetReferencingRelationshipInstances(ModelRelationshipClass relationshipType);
63 | IEnumerable GetReferencingRelationshipInstances(ModelRelationshipClass relationshipType, DacQueryScopes queryScopes);
64 | string GetScript();
65 | SourceInformation GetSourceInformation();
66 | ModelTypeClass ObjectType { get; }
67 | object this[ModelPropertyClass property] { get; }
68 | bool TryGetAst(out TSqlScript objectAst);
69 | bool TryGetScript(out string objectScript);
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/DacFxStronglyTypedModel/ISqlModelElementReference.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | //
4 | // The MIT License (MIT)
5 | //
6 | // Copyright (c) 2015 Microsoft
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 | //------------------------------------------------------------------------------
27 | using Microsoft.SqlServer.Dac.Model;
28 | namespace Microsoft.SqlServer.Dac.Extensions.Prototype
29 | {
30 |
31 | public interface ISqlModelElementReference : ISqlModelElement
32 | {
33 | T GetMetadataProperty(ModelPropertyClass property);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/DacFxStronglyTypedModel/Interfaces.tt:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | //
4 | // The MIT License (MIT)
5 | //
6 | // Copyright (c) 2015 Microsoft
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 | //------------------------------------------------------------------------------
27 | <#@ template debug="false" hostspecific="true" language="C#" #>
28 | <#@ assembly name="System.Core" #>
29 | <#@ assembly name="System.Xml" #>
30 | <#@ import namespace="System.Linq" #>
31 | <#@ import namespace="System.Text" #>
32 | <#@ import namespace="System" #>
33 | <#@ import namespace="System.Xml" #>
34 | <#@ import namespace="System.Collections.Generic" #>
35 | <#@ assembly name="$(DacFxExternals)\Microsoft.SqlServer.Dac.Extensions.dll" #>
36 | <#@ import namespace="Microsoft.SqlServer.Dac.Model"#>
37 | <#@ output extension=".cs" #>
38 | <#@ include file="Utils.tt" #>
39 | namespace <#=NamespaceName#>
40 | {
41 | using System;
42 | using System.Linq;
43 | using Microsoft.SqlServer.Server;
44 | using Microsoft.SqlServer.Dac.Model;
45 | using System.Collections.Generic;
46 | <#
47 | var overrides = LoadOverrides(this.Host.TemplateFile);
48 | string interfacePrefix;
49 |
50 | foreach(SqlServerVersion currentSQLVersion in GetSqlServerVersionValues())
51 | {
52 | interfacePrefix = GetInterfacePrefix(currentSQLVersion);
53 | foreach(var type in ModelSchema.SchemaInstance.AllTypes)
54 | {
55 | string className = interfacePrefix+ ClassNamePrefix +type.Name;
56 | ModelEntry modelEntry;
57 | overrides.TryGetValue(type.Name, out modelEntry);
58 |
59 | #>
60 | public interface <#= className #>Reference : <#= className #>
61 | {
62 | }
63 | public interface <#= className #> : ISqlModelElement
64 | {
65 | <#
66 | foreach (var property in type.Properties.OrderBy(p => p.Name))
67 | {
68 | if(!SupportsVersion(property.SupportedPlatforms, currentSQLVersion))
69 | {
70 | continue;
71 | }
72 | bool useGenericGetter;
73 | string typeName = GetPropertyTypeName(property.DataType, out useGenericGetter);
74 | string propertyName = GetPropertyName(property, modelEntry);
75 | #>
76 | <#= typeName #> <#= propertyName #>
77 | {
78 | get;
79 | }
80 | <#
81 | }// end property loop
82 |
83 |
84 | // begin relationship loop
85 | foreach (var relationship in type.Relationships.OrderBy( r => r.Name))
86 | {
87 | if (!SupportsVersion(relationship.SupportedPlatforms, currentSQLVersion))
88 | {
89 | // skip unsupported properties
90 | continue;
91 | }
92 | string returnType = DefaultReturnType;
93 | if(modelEntry != null)
94 | {
95 | RelationshipOverride localoverride;
96 | if(modelEntry.RelationshipOverrides.TryGetValue(relationship.Name, out localoverride))
97 | {
98 | if(localoverride.Specialize)
99 | {
100 | // specialize the return type to match the sql version interface name
101 | returnType = string.Format("{0}.{1}{2}", localoverride.ReturnTypeNamespace,interfacePrefix, localoverride.ReturnType);
102 | }
103 | else
104 | {
105 | // return type is not specialized for each sql version interface.
106 | returnType = string.Format("{0}.{1}", localoverride.ReturnTypeNamespace, localoverride.ReturnType);
107 | }
108 | }
109 | }
110 | #>
111 | //<#=relationship.Type#>
112 | IEnumerable<<#=returnType#>> <#=relationship.Name #>
113 | {
114 | get;
115 | }
116 | <#
117 | } //end foreach relationship
118 | #>
119 | }
120 | <#
121 | }
122 | }
123 | #>
124 | }
--------------------------------------------------------------------------------
/DacFxStronglyTypedModel/MarkerInterfaces.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.SqlServer.Dac.Model;
2 | //------------------------------------------------------------------------------
3 | //
4 | //
5 | // The MIT License (MIT)
6 | //
7 | // Copyright (c) 2015 Microsoft
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in all
17 | // copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 | // SOFTWARE.
26 | //
27 | //------------------------------------------------------------------------------
28 | using System;
29 | using System.Collections.Generic;
30 | using System.Linq;
31 | using System.Text;
32 |
33 | namespace Microsoft.SqlServer.Dac.Extensions.Prototype
34 | {
35 |
36 | public interface ISqlSecurityPrincipal : ISqlModelElement { }
37 |
38 | public interface IServerSecurityPrincipal : ISqlSecurityPrincipal { }
39 |
40 | public interface ISqlDatabaseSecurityPrincipal : ISqlSecurityPrincipal, ISqlObjectAuthorizer{ }
41 |
42 | public sealed class UnresolvedISqlDatabaseSecurityPrincipalElement : TSqlModelElementReference, ISqlDatabaseSecurityPrincipal
43 | {
44 | public UnresolvedISqlDatabaseSecurityPrincipalElement(Model.ModelRelationshipInstance relationshipReference) : base(relationshipReference)
45 | {
46 |
47 | }
48 | }
49 | public interface ISqlSecurable : ISqlModelElement { }
50 |
51 | public sealed class UnresolvedISqlSecurableElement : TSqlModelElementReference, ISqlSecurable
52 | {
53 | public UnresolvedISqlSecurableElement(Model.ModelRelationshipInstance relationshipReference):base(relationshipReference)
54 | { }
55 | }
56 |
57 | public interface ISpecifiesIndex : ISqlModelElement
58 | {
59 | IEnumerable Indexes { get; }
60 | }
61 |
62 | public sealed class UnresolvedISpecifiesIndexElement: TSqlModelElementReference, ISpecifiesIndex
63 | {
64 | public UnresolvedISpecifiesIndexElement(Model.ModelRelationshipInstance instance)
65 | : base(instance)
66 | {
67 | }
68 |
69 | public IEnumerable Indexes
70 | {
71 | get { throw new UnresolvedElementException(ModelMessages.UnresolvedObject); }
72 | }
73 | }
74 |
75 | public interface ISpecifiesDmlTrigger : ISqlModelElement
76 | {
77 | IEnumerable Triggers { get; }
78 | }
79 |
80 | public interface ISqlColumnSource : ISqlModelElement
81 | {
82 | IEnumerable Columns { get; }
83 | }
84 | public interface ISqlPromotedNodePath : ISqlModelElement { }
85 |
86 | public sealed class UnresolvedISqlPromotedNodePathElement : TSqlModelElementReference, ISqlPromotedNodePath
87 | {
88 | public UnresolvedISqlPromotedNodePathElement(Model.ModelRelationshipInstance relationshipReference)
89 | : base(relationshipReference)
90 | { }
91 | }
92 |
93 | public interface ISqlIndex : ISqlModelElement { }
94 | public interface ITableTypeConstraint : ISqlModelElement { }
95 | public interface IProtocolSpecifier : ISqlModelElement { }
96 | public interface IEndpointLanguageSpecifier : ISqlModelElement { }
97 |
98 |
99 | #region IExtendedProprtyHost
100 | public interface IExtendedPropertyHost : ISqlModelElement { }
101 |
102 | //TODO: Collect all extended property hosts. Some added but lots missing
103 | #endregion
104 |
105 | #region ISqlObjectAuthorizer
106 | public interface ISqlObjectAuthorizer : ISqlModelElement { }
107 |
108 | public sealed class UnresolvedISqlObjectAuthorizerElement : TSqlModelElementReference, ISqlObjectAuthorizer
109 | {
110 | public UnresolvedISqlObjectAuthorizerElement(Model.ModelRelationshipInstance relationshipReference) : base(relationshipReference)
111 | {
112 |
113 | }
114 | }
115 |
116 | // TODO: Collect all Authorizers
117 | #endregion
118 |
119 | public interface ISpecifiesStorage : ISqlModelElement
120 | {
121 | IEnumerable DataCompressionOptions { get; }
122 |
123 | }
124 |
125 | public interface ISqlDataType: ISqlModelElement
126 | {
127 | }
128 |
129 | public sealed class UnresolvedISqlDataTypeElement : TSqlModelElementReference, ISqlDataType
130 | {
131 | public UnresolvedISqlDataTypeElement(Model.ModelRelationshipInstance relationshipReference)
132 | : base(relationshipReference)
133 | { }
134 | }
135 | }
136 |
137 |
--------------------------------------------------------------------------------
/DacFxStronglyTypedModel/ModelMessages.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.34209
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace Microsoft.SqlServer.Dac.Extensions.Prototype {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class ModelMessages {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal ModelMessages() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.SqlServer.Dac.Extensions.Prototype.ModelMessages", typeof(ModelMessages).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | ///
64 | /// Looks up a localized string similar to Model Type Class {0} does not match the TSqlObject ObjectType {1}.
65 | ///
66 | internal static string InvalidObjectType {
67 | get {
68 | return ResourceManager.GetString("InvalidObjectType", resourceCulture);
69 | }
70 | }
71 |
72 | ///
73 | /// Looks up a localized string similar to Underlying object {0} is unresolved..
74 | ///
75 | internal static string UnresolvedObject {
76 | get {
77 | return ResourceManager.GetString("UnresolvedObject", resourceCulture);
78 | }
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/DacFxStronglyTypedModel/ModelMessages.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | Model Type Class {0} does not match the TSqlObject ObjectType {1}
122 |
123 |
124 | Underlying object {0} is unresolved.
125 |
126 |
--------------------------------------------------------------------------------
/DacFxStronglyTypedModel/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("DacFxStronglyTypedModel")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("DacFxStronglyTypedModel")]
13 | [assembly: AssemblyCopyright("Copyright © 2014")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("42196f12-dcd8-451f-8b2b-cc63ed40f9a2")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/DacFxStronglyTypedModel/TSqlModelElementReference.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | //
4 | // The MIT License (MIT)
5 | //
6 | // Copyright (c) 2015 Microsoft
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 | //------------------------------------------------------------------------------
27 |
28 | using Microsoft.SqlServer.Dac.Model;
29 | using System;
30 | using System.Collections.Generic;
31 | using System.Globalization;
32 |
33 | namespace Microsoft.SqlServer.Dac.Extensions.Prototype
34 | {
35 | public class TSqlModelElementReference : TSqlModelElement, ISqlModelElementReference
36 | {
37 | private ModelRelationshipInstance relationshipInstance;
38 | private ModelTypeClass predefinedTypeClass;
39 |
40 |
41 | public TSqlModelElementReference(ModelRelationshipInstance relationshipReference) :
42 | base()
43 | {
44 | relationshipInstance = relationshipReference;
45 | }
46 | public TSqlModelElementReference(ModelRelationshipInstance relationshipReference, ModelTypeClass typeClass) :
47 | this(relationshipReference)
48 | {
49 |
50 | if (relationshipInstance.Object != null && relationshipInstance.Object.ObjectType != typeClass)
51 | {
52 | throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
53 | ModelMessages.InvalidObjectType, relationshipInstance.Object.ObjectType.Name, typeClass.Name),
54 | "typeClass");
55 | }
56 |
57 | predefinedTypeClass = typeClass;
58 | }
59 |
60 | public override ObjectIdentifier Name
61 | {
62 | get
63 | {
64 | return relationshipInstance.ObjectName;
65 | }
66 | }
67 |
68 | public override ModelTypeClass ObjectType
69 | {
70 | get
71 | {
72 | if (IsResolved())
73 | {
74 | return base.ObjectType;
75 | }
76 | else
77 | {
78 | // when object is unresolved default to the predefined ModelTypClass
79 | return predefinedTypeClass;
80 | }
81 | }
82 | }
83 | public bool IsResolved()
84 | {
85 | return relationshipInstance.Object != null;
86 | }
87 |
88 | public override TSqlObject Element
89 | {
90 | get
91 | {
92 | // Verify the Element is resolved.
93 | if (!IsResolved())
94 | {
95 | throw new UnresolvedElementException(
96 | string.Format(CultureInfo.CurrentUICulture,
97 | ModelMessages.UnresolvedObject,
98 | relationshipInstance.ObjectName));
99 | }
100 | return relationshipInstance.Object;
101 | }
102 |
103 | }
104 |
105 | public T GetMetadataProperty(ModelPropertyClass property)
106 | {
107 | return relationshipInstance.GetProperty(property);
108 | }
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/DacFxStronglyTypedModel/UnresolvedElementException.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | //
4 | // The MIT License (MIT)
5 | //
6 | // Copyright (c) 2015 Microsoft
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 | //------------------------------------------------------------------------------
27 | using System;
28 | using System.Collections.Generic;
29 | using System.Linq;
30 | using System.Runtime.Serialization;
31 | using System.Text;
32 | using System.Threading.Tasks;
33 |
34 | namespace Microsoft.SqlServer.Dac.Extensions.Prototype
35 | {
36 | ///
37 | /// Thrown when a the referenced element is not resolvable. This happens when there 0 or more than 1 candidate elements
38 | /// that the reference can resolve to.
39 | ///
40 | public sealed class UnresolvedElementException : Exception
41 | {
42 | public UnresolvedElementException() { }
43 | public UnresolvedElementException(string message) : base(message) { }
44 | public UnresolvedElementException(string message, Exception innerException) : base(message, innerException) { }
45 | public UnresolvedElementException(SerializationInfo info, StreamingContext context) : base(info, context) { }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/DacFxStronglyTypedModel/Utils.cs:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/DacFxStronglyTypedModel/VersionSpecificImplementations.tt:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | //
4 | // The MIT License (MIT)
5 | //
6 | // Copyright (c) 2015 Microsoft
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 | //------------------------------------------------------------------------------
27 | <#@ template debug="false" hostspecific="true" language="C#" #>
28 | <#@ assembly name="System.Core" #>
29 | <#@ assembly name="System.Xml" #>
30 | <#@ import namespace="System.Linq" #>
31 | <#@ import namespace="System.Text" #>
32 | <#@ import namespace="System.Xml" #>
33 | <#@ import namespace="System.Collections.Generic" #>
34 | <#@ assembly name="$(DacFxExternals)\Microsoft.SqlServer.Dac.Extensions.dll" #>
35 | <#@ import namespace="Microsoft.SqlServer.Dac.Model"#>
36 | <#@ output extension=".cs" #>
37 | <#@ include file="Utils.tt" #>
38 | namespace <#=NamespaceName#>
39 | {
40 | using System;
41 | using System.Linq;
42 | using Microsoft.SqlServer.Server;
43 | using Microsoft.SqlServer.Dac.Model;
44 | using System.Collections.Generic;
45 | <#
46 | var overrides = LoadOverrides(this.Host.TemplateFile);
47 | string typePrefix;
48 | foreach(SqlServerVersion currentSQLVersion in GetSqlServerVersionValues())
49 | {
50 | typePrefix = GetInterfacePrefix(currentSQLVersion);
51 | foreach(var type in ModelSchema.SchemaInstance.AllTypes)
52 | {
53 | if(!SupportsVersion(type.SupportedPlatforms, currentSQLVersion))
54 | {
55 | // skipping type as it does not support the platform
56 | continue;
57 | }
58 | string interfaceName = typePrefix + ClassNamePrefix + type.Name;
59 | ModelEntry modelEntry;
60 | if(!overrides.TryGetValue(type.Name, out modelEntry))
61 | {
62 | modelEntry = null;
63 | }
64 | #>
65 | ///
66 | /// Explicit implementation of .
67 | ///
68 | public partial class <#= ClassNamePrefix + type.Name#> : <#=interfaceName#>
69 | {
70 | <#
71 | foreach (var property in type.Properties.OrderBy(p => p.Name))
72 | {
73 | if(!SupportsVersion(property.SupportedPlatforms, currentSQLVersion))
74 | {
75 | continue;
76 | }
77 | bool useGenericGetter;
78 | string typeName = GetPropertyTypeName(property.DataType, out useGenericGetter);
79 | string propertyName = GetPropertyName(property, modelEntry);
80 | #>
81 | <#= typeName #> <#=interfaceName#>.<#= propertyName #>
82 | {
83 | get { return this.<#=propertyName#>;}
84 | }
85 | <#
86 | }// end property loop
87 |
88 | // begin relationship loop
89 | foreach (var relationship in type.Relationships.OrderBy( r => r.Name))
90 | {
91 | if (!SupportsVersion(relationship.SupportedPlatforms, currentSQLVersion))
92 | {
93 | // skip unsupported properties
94 | continue;
95 | }
96 | string returnType = DefaultReturnType;
97 | string castExpression = "";
98 | if(modelEntry != null)
99 | { RelationshipOverride localoverride;
100 | if(modelEntry.RelationshipOverrides.TryGetValue(relationship.Name, out localoverride))
101 | {
102 | if(localoverride.Specialize)
103 | {
104 | // specialize the return type for the sql server version
105 | returnType = string.Format("{0}.{1}{2}", localoverride.ReturnTypeNamespace, typePrefix, localoverride.ReturnType);
106 | castExpression = string.Format(".Cast<{0}>()", returnType);
107 | }
108 | else
109 | {
110 | // do not specialize the return type for the sql server version
111 | returnType = string.Format("{0}.{1}", localoverride.ReturnTypeNamespace, localoverride.ReturnType);
112 | }
113 | }
114 | }
115 | #>
116 |
117 | // <#=relationship.Type#> relationship
118 | IEnumerable<<#=returnType#>> <#=interfaceName#>.<#=relationship.Name #>
119 | {
120 | get
121 | {
122 | return this.<#=relationship.Name + castExpression#>;
123 | }
124 | }
125 | <#
126 | } //end foreach relationship
127 | #>
128 | }
129 | <#
130 | }
131 | }
132 | #>
133 | }
--------------------------------------------------------------------------------
/DacFxStronglyTypedModel/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/DacPublicSamples.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.22823.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleConsoleApp", "SampleConsoleApp\SampleConsoleApp.csproj", "{7855389B-A1F0-4A7C-A83A-38EEF5B73F9A}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Samples", "Samples\Samples.csproj", "{C1C2B521-22B6-4124-AAEC-A5E1FCAB0DFA}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleTests", "SampleTests\SampleTests.csproj", "{E8F7142C-412D-40A8-AC5E-C90339A8C559}"
11 | EndProject
12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RuleSamples", "RuleSamples\RuleSamples.csproj", "{18E096E9-6A3D-4124-B908-9C39A425F7BE}"
13 | EndProject
14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RuleTests", "RuleTests\RuleTests.csproj", "{DF142FCD-E8E0-4841-BDB9-C9974F09068D}"
15 | EndProject
16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DacFxStronglyTypedModel", "DacFxStronglyTypedModel\DacFxStronglyTypedModel.csproj", "{832ECF86-C071-4628-A8B7-2529D8A7BDBC}"
17 | EndProject
18 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestUtils", "TestUtils\TestUtils.csproj", "{EDF01D79-66D0-496C-82D2-431831564817}"
19 | EndProject
20 | Global
21 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
22 | Debug|Any CPU = Debug|Any CPU
23 | Release|Any CPU = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
26 | {7855389B-A1F0-4A7C-A83A-38EEF5B73F9A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27 | {7855389B-A1F0-4A7C-A83A-38EEF5B73F9A}.Debug|Any CPU.Build.0 = Debug|Any CPU
28 | {7855389B-A1F0-4A7C-A83A-38EEF5B73F9A}.Release|Any CPU.ActiveCfg = Release|Any CPU
29 | {7855389B-A1F0-4A7C-A83A-38EEF5B73F9A}.Release|Any CPU.Build.0 = Release|Any CPU
30 | {C1C2B521-22B6-4124-AAEC-A5E1FCAB0DFA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
31 | {C1C2B521-22B6-4124-AAEC-A5E1FCAB0DFA}.Debug|Any CPU.Build.0 = Debug|Any CPU
32 | {C1C2B521-22B6-4124-AAEC-A5E1FCAB0DFA}.Release|Any CPU.ActiveCfg = Release|Any CPU
33 | {C1C2B521-22B6-4124-AAEC-A5E1FCAB0DFA}.Release|Any CPU.Build.0 = Release|Any CPU
34 | {E8F7142C-412D-40A8-AC5E-C90339A8C559}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
35 | {E8F7142C-412D-40A8-AC5E-C90339A8C559}.Debug|Any CPU.Build.0 = Debug|Any CPU
36 | {E8F7142C-412D-40A8-AC5E-C90339A8C559}.Release|Any CPU.ActiveCfg = Release|Any CPU
37 | {E8F7142C-412D-40A8-AC5E-C90339A8C559}.Release|Any CPU.Build.0 = Release|Any CPU
38 | {18E096E9-6A3D-4124-B908-9C39A425F7BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
39 | {18E096E9-6A3D-4124-B908-9C39A425F7BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
40 | {18E096E9-6A3D-4124-B908-9C39A425F7BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
41 | {18E096E9-6A3D-4124-B908-9C39A425F7BE}.Release|Any CPU.Build.0 = Release|Any CPU
42 | {DF142FCD-E8E0-4841-BDB9-C9974F09068D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
43 | {DF142FCD-E8E0-4841-BDB9-C9974F09068D}.Debug|Any CPU.Build.0 = Debug|Any CPU
44 | {DF142FCD-E8E0-4841-BDB9-C9974F09068D}.Release|Any CPU.ActiveCfg = Release|Any CPU
45 | {DF142FCD-E8E0-4841-BDB9-C9974F09068D}.Release|Any CPU.Build.0 = Release|Any CPU
46 | {832ECF86-C071-4628-A8B7-2529D8A7BDBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
47 | {832ECF86-C071-4628-A8B7-2529D8A7BDBC}.Debug|Any CPU.Build.0 = Debug|Any CPU
48 | {832ECF86-C071-4628-A8B7-2529D8A7BDBC}.Release|Any CPU.ActiveCfg = Release|Any CPU
49 | {832ECF86-C071-4628-A8B7-2529D8A7BDBC}.Release|Any CPU.Build.0 = Release|Any CPU
50 | {EDF01D79-66D0-496C-82D2-431831564817}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
51 | {EDF01D79-66D0-496C-82D2-431831564817}.Debug|Any CPU.Build.0 = Debug|Any CPU
52 | {EDF01D79-66D0-496C-82D2-431831564817}.Release|Any CPU.ActiveCfg = Release|Any CPU
53 | {EDF01D79-66D0-496C-82D2-431831564817}.Release|Any CPU.Build.0 = Release|Any CPU
54 | EndGlobalSection
55 | GlobalSection(SolutionProperties) = preSolution
56 | HideSolutionNode = FALSE
57 | EndGlobalSection
58 | EndGlobal
59 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Microsoft
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DACExtensions
2 |
3 |
4 | > [!IMPORTANT]
5 | > This repository has been archived and the samples are no longer maintained. The development of DacFx and SQL projects is active, including the areas of extensibility and code analysis as seen in this repository. We welcome your feedback and issue reports over at https://github.com/microsoft/dacfx.
6 |
7 | ## Project Description
8 | DACExtensions contains API extensions and samples using the [DacFx API](https://msdn.microsoft.com/en-us/library/dn645454.aspx) to develop Data-Tier Applications.
9 |
10 | These extensions and samples include an improved object model, deployment contributors and static code analysis rules that can be used with Visual Studio or directly with the DacFx public API.
11 |
12 | ## Background Information
13 | SQL Server Data Tools is built into Visual Studio 2013. For other versions of visual studio you can download SQL Server Data Tools from the [Data Developer Center](https://msdn.microsoft.com/en-us/data/hh297027)
14 |
15 | SQL Server Data Tools provides an integrated environment for database developers to carry out all of their database design work for any SQL Server Platform.
16 |
17 | DacFx is the core technology the SQL Server Data Tools leverages for incremental database deployments, modelling and validation of database schemas and other key functionality. DacFx provides a DacServices API that supports programmatic deployment of Dacpac files.
18 | DacFx has a number of public extensibility points that customers can implement. Some possible functionality includes:
19 |
20 | * Programmatic examinations of database schemas (as represented in a Visual Studio database project, a Dacpac and even a target database when used during deployment)
21 | * Modification of the deployment plans used to incrementally deploy schema updates from a Dacpac to a database
22 | * Static Code Analysis rules provide build-time support for analyzing the database schema and warning users of potential issues.
23 |
24 | These samples are primarily intended to show users how to create their own extensions, test them and use them in deployment. They include solutions to real customer problems and can be used as-is if you have the same issue. Ideally you will take this project, extend it and create your own solutions.
25 |
26 | ## Prerequisites
27 | An installation of SQL Server Data Tools or DacFx is required to run these samples. The sample projects include references to DLLs in a Visual Studio installation with the most recent release of SQL Server Data Tools.
28 |
29 | * For Visual Studio 2013 the install directory will is "%ProgramFiles(x86)%\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\Microsoft\SQLDB\DAC\120".
30 | * This is set as the current hint path in all sample projects
31 | * For Visual Studio 2012 the install directory is "%ProgramFiles(x86)%\Microsoft Visual Studio 11.0\Common7\IDE\Extensions\Microsoft\SQLDB\DAC\120".
32 | * The hint path in all sample projects must be updated if you want to target Visual Studio 2012 DLLs.
33 | * For DacFx the install directory is "%ProgramFiles(x86)%\Microsoft Server Server \Common7\IDE\Extensions\Microsoft\SQLDB\DAC\120".
34 | * The hint path in all sample projects must be updated if you want to target the DacFx DLLs.
35 |
36 | This project uses Git for source code control. Visual Studio 2013 has Git support built in, and for Visual Studio 2012 please download the Visual Studio Tools for Git plugin.
37 |
38 | ## Usage
39 | The samples in this project are provided as-is. To run the samples, we recommend you download the source code and attach a debugger while running the sample console application and unit test code.
40 |
41 | The full tutorial explaining how to use the public APIs can be found [here][dacfxturorial].
42 |
43 | ## Samples Installation
44 |
45 | These samples assume the latest SQL Server Data Tools updates for Visual Studio 2013 are installed.
46 | To develop using Visual Studio 2012 please modify the .csproj files to change
47 | "C:\Program Files (x86)\Microsoft Visual Studio 12.0" to "C:\Program Files (x86)\Microsoft Visual Studio 11.0", and ensure the latest version of SQL Server Data Tools is installed for Visual Studio 2012.
48 |
49 | These samples are intended to work in tandem with the walkthroughs at
50 | [http://msdn.microsoft.com/en-us/library/dn268597(v=vs.103).aspx][msdn] and with the standard
51 | SQL Server Data Tools help documentation. They show how to bootstrap an extensions library for Static
52 | Code Analysis rules and contributors and test them without installing anything into
53 | Visual Studio.
54 |
55 | If you wish to install any samples DLL into visual studio you need to sign the DLLs per
56 | the walkthrough instructions:
57 |
58 | To sign and build the assembly
59 |
60 | * On the Project menu, click Properties .
61 | * Click the Signing tab.
62 | * Click Sign the assembly.
63 | * In Choose a strong name key file , click .
64 | * In the Create Strong Name Key dialog box, in Key file name , type MyRefKey.
65 | * (optional) You can specify a password for your strong name key file.
66 | * Click OK.
67 | * On the File menu, click Save All.
68 | * On the Build menu, click Build Solution.
69 |
70 |
71 | Then copy them to the extension installation directory:
72 |
73 | * VS 2013: %ProgramFiles(x86)%\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\Microsoft\SQLDB\DAC\120\Extensions
74 | * VS 2012: %ProgramFiles(x86)%\Microsoft Visual Studio 11.0\Common7\IDE\Extensions\Microsoft\SQLDB\DAC\120\Extensions
75 |
76 | ## Code of Conduct
77 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
78 |
79 | [msdn]:http://msdn.microsoft.com/en-us/library/dn268597(v=vs.103).aspx
80 | [dacfxturorial]:http://blogs.msdn.com/b/ssdt/archive/2013/12/23/dacfx-public-model-tutorial.aspx
81 |
--------------------------------------------------------------------------------
/RuleSamples/LocalizedExportCodeAnalysisRuleAttribute.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | //
4 | // The MIT License (MIT)
5 | //
6 | // Copyright (c) 2015 Microsoft
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 | //------------------------------------------------------------------------------
27 |
28 | using Microsoft.SqlServer.Dac.CodeAnalysis;
29 | using System;
30 | using System.Globalization;
31 | using System.Reflection;
32 | using System.Resources;
33 |
34 | namespace Public.Dac.Samples.Rules
35 | {
36 | ///
37 | /// This is an example of a localized export attribute. These can be very useful in the case where
38 | /// you need localized resource strings for things like the display name and description of a rule.
39 | ///
40 | /// All of the export attributes provided by the DAC API can be localized, and internally a very
41 | /// similar structure is used. If you do not need to perform localization of any resources it's easier to use the
42 | /// directly.
43 | ///
44 | ///
45 | internal class LocalizedExportCodeAnalysisRuleAttribute : ExportCodeAnalysisRuleAttribute
46 | {
47 | private readonly string _resourceBaseName;
48 | private readonly string _displayNameResourceId;
49 | private readonly string _descriptionResourceId;
50 |
51 | private ResourceManager _resourceManager;
52 | private string _displayName;
53 | private string _descriptionValue;
54 |
55 | ///
56 | /// Creates the attribute, with the specified rule ID, the fully qualified
57 | /// name of the resource file that will be used for looking up display name
58 | /// and description, and the Ids of those resources inside the resource file.
59 | ///
60 | public LocalizedExportCodeAnalysisRuleAttribute(
61 | string id,
62 | string resourceBaseName,
63 | string displayNameResourceId,
64 | string descriptionResourceId)
65 | : base(id, null)
66 | {
67 | _resourceBaseName = resourceBaseName;
68 | _displayNameResourceId = displayNameResourceId;
69 | _descriptionResourceId = descriptionResourceId;
70 | }
71 |
72 | ///
73 | /// Rules in a different assembly would need to overwrite this
74 | ///
75 | ///
76 | protected virtual Assembly GetAssembly()
77 | {
78 | return GetType().Assembly;
79 | }
80 |
81 | private void EnsureResourceManagerInitialized()
82 | {
83 | var resourceAssembly = GetAssembly();
84 |
85 | try
86 | {
87 | _resourceManager = new ResourceManager(_resourceBaseName, resourceAssembly);
88 | }
89 | catch (Exception ex)
90 | {
91 | var msg = String.Format(CultureInfo.CurrentCulture, RuleResources.CannotCreateResourceManager, _resourceBaseName, resourceAssembly);
92 | throw new RuleException(msg, ex);
93 | }
94 | }
95 |
96 | private string GetResourceString(string resourceId)
97 | {
98 | if (string.IsNullOrWhiteSpace(resourceId))
99 | {
100 | return string.Empty;
101 | }
102 | EnsureResourceManagerInitialized();
103 | return _resourceManager.GetString(resourceId, CultureInfo.CurrentUICulture);
104 | }
105 |
106 | ///
107 | /// Overrides the standard DisplayName and looks up its value inside a resources file
108 | ///
109 | public override string DisplayName
110 | {
111 | get
112 | {
113 | if (_displayName == null)
114 | {
115 | _displayName = GetResourceString(_displayNameResourceId);
116 | }
117 | return _displayName;
118 | }
119 | }
120 |
121 | ///
122 | /// Overrides the standard Description and looks up its value inside a resources file
123 | ///
124 | public override string Description
125 | {
126 | get
127 | {
128 | if (_descriptionValue == null)
129 | {
130 | // Using the descriptionResourceId as the key for looking up the description in the resources file.
131 | _descriptionValue = GetResourceString(_descriptionResourceId);
132 | }
133 | return _descriptionValue;
134 | }
135 | }
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/RuleSamples/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("RuleSamples")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("RuleSamples")]
13 | [assembly: AssemblyCopyright("Copyright © 2014")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("6936afeb-f7c1-4cd8-8cdd-71d9de761ba3")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/RuleSamples/RuleConstants.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | //
4 | // The MIT License (MIT)
5 | //
6 | // Copyright (c) 2015 Microsoft
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 | //------------------------------------------------------------------------------
27 |
28 | using Microsoft.SqlServer.Dac.Extensibility;
29 |
30 | namespace Public.Dac.Samples.Rules
31 | {
32 | internal static class RuleConstants
33 | {
34 | ///
35 | /// The name of the resources file to use when looking up rule resources
36 | ///
37 | public const string ResourceBaseName = "Public.Dac.Samples.Rules.RuleResources";
38 |
39 | ///
40 | /// Lookup name inside the resources file for the rule name
41 | ///
42 | public const string AvoidWaitForDelay_RuleName = "AvoidWaitForDelay_RuleName";
43 | ///
44 | /// Lookup ID inside the resources file for the description
45 | ///
46 | public const string AvoidWaitForDelay_ProblemDescription = "AvoidWaitForDelay_ProblemDescription";
47 |
48 | ///
49 | /// Lookup name inside the resources file for the rule name
50 | ///
51 | public const string InMemoryBinCollection_RuleName = "InMemoryBinCollection_RuleName";
52 | ///
53 | /// Lookup ID inside the resources file for the description
54 | ///
55 | public const string InMemoryBinCollection_ProblemDescription = "InMemoryBinCollection_ProblemDescription";
56 |
57 | ///
58 | /// Lookup name inside the resources file for the rule name
59 | ///
60 | public const string ViewsOnMemoryOptimizedTable_RuleName = "ViewsOnMemoryOptimizedTable_RuleName";
61 |
62 | public const string CapitalizedNames_RuleName = "CapitalizedNames_RuleName";
63 |
64 | public const string CapitalizedNames_ProblemDescription = "CapitalizedNames_ProblemDescription";
65 |
66 | ///
67 | /// The design category (should not be localized)
68 | ///
69 | public const string CategoryDesign = "Design";
70 |
71 | public const string CategoryPerformance = "Performance";
72 |
73 | public const string CategoryNaming = "Naming";
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/RuleSamples/RuleSamples.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {18E096E9-6A3D-4124-B908-9C39A425F7BE}
8 | Library
9 | Properties
10 | Public.Dac.Samples.Rules
11 | Public.Dac.Samples.Rules
12 | v4.6
13 | 512
14 |
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 |
33 |
34 |
35 | ..\packages\Microsoft.SqlServer.DacFx.x64.150.4826.1\lib\net46\Microsoft.Data.Tools.Schema.Sql.dll
36 |
37 |
38 | ..\packages\Microsoft.SqlServer.DacFx.x64.150.4826.1\lib\net46\Microsoft.Data.Tools.Utilities.dll
39 |
40 |
41 | ..\packages\Microsoft.SqlServer.DacFx.x64.150.4826.1\lib\net46\Microsoft.SqlServer.Dac.dll
42 |
43 |
44 | ..\packages\Microsoft.SqlServer.DacFx.x64.150.4826.1\lib\net46\Microsoft.SqlServer.Dac.Extensions.dll
45 |
46 |
47 | ..\packages\Microsoft.SqlServer.DacFx.x64.150.4826.1\lib\net46\Microsoft.SqlServer.TransactSql.ScriptDom.dll
48 |
49 |
50 | ..\packages\Microsoft.SqlServer.DacFx.x64.150.4826.1\lib\net46\Microsoft.SqlServer.Types.dll
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | True
71 | True
72 | RuleResources.resx
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 | ResXFileCodeGenerator
82 | RuleResources.Designer.cs
83 |
84 |
85 |
86 |
87 |
88 |
89 |
96 |
--------------------------------------------------------------------------------
/RuleSamples/RuleUtils.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | //
4 | // The MIT License (MIT)
5 | //
6 | // Copyright (c) 2015 Microsoft
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 | //------------------------------------------------------------------------------
27 |
28 | using Microsoft.SqlServer.Dac.CodeAnalysis;
29 | using Microsoft.SqlServer.Dac.Model;
30 |
31 | namespace Public.Dac.Samples.Rules
32 | {
33 | internal static class RuleUtils
34 | {
35 | ///
36 | /// Gets a formatted element name with the default style
37 | ///
38 | public static string GetElementName(SqlRuleExecutionContext ruleExecutionContext, TSqlObject modelElement)
39 | {
40 | return GetElementName(modelElement, ruleExecutionContext, ElementNameStyle.EscapedFullyQualifiedName);
41 | }
42 |
43 | ///
44 | /// Gets a formatted element name
45 | ///
46 | public static string GetElementName(TSqlObject modelElement, SqlRuleExecutionContext ruleExecutionContext, ElementNameStyle style)
47 | {
48 | // Get the element name using the built in DisplayServices. This provides a number of useful formatting options to
49 | // make a name user-readable
50 | var displayServices = ruleExecutionContext.SchemaModel.DisplayServices;
51 | string elementName = displayServices.GetElementName(modelElement, style);
52 | return elementName;
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/RuleSamples/TableNameEndingInViewRule.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | //
4 | // The MIT License (MIT)
5 | //
6 | // Copyright (c) 2015 Microsoft
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 | //------------------------------------------------------------------------------
27 |
28 | using Microsoft.SqlServer.Dac.CodeAnalysis;
29 | using Microsoft.SqlServer.Dac.Model;
30 | using System;
31 | using System.Collections.Generic;
32 | using System.Linq;
33 |
34 | namespace Public.Dac.Samples.Rules
35 | {
36 | ///
37 | /// This is probably the simplest possible example of a rule that uses the public model API to analyze properties of elements.
38 | /// In this case any table whose name ends in "View" is treated as a problem.
39 | ///
40 | /// This does not use a localized export attribute, unlike the and other rules. It is
41 | /// not recommended that you use this code in a real world scenario
42 | ///
43 | [ExportCodeAnalysisRule(TableNameEndingInViewRule.RuleId,
44 | TableNameEndingInViewRule.RuleDisplayName,
45 | Description = "Table names should not end in 'View'",
46 | Category = "Naming",
47 | RuleScope = SqlRuleScope.Element)]
48 | public sealed class TableNameEndingInViewRule : SqlCodeAnalysisRule
49 | {
50 | public const string RuleId = "Public.Dac.Samples.Rules.TableNameEndingInViewRule";
51 | public const string RuleDisplayName = "SqlSampleRule001";
52 | public const string NameEndingInViewMsgFormat = "Table name {0} ends in View. This can cause confusion and should be avoided";
53 |
54 | ///
55 | /// For Element-scoped rules the SupportedElementTypes must be defined, ideally inside the constructor.
56 | /// Only objects that match one of these types will be passed to the method, so this
57 | /// helps avoid the need to iterate over the model and select the object to be processed.
58 | ///
59 | /// This rule only operates on regular Tables.
60 | ///
61 | public TableNameEndingInViewRule()
62 | {
63 | SupportedElementTypes = new[] { Table.TypeClass };
64 | }
65 |
66 | ///
67 | /// Analysis is quite simple - the table's name is examined and if it ends with "View" then a problem
68 | /// is created
69 | ///
70 | ///
71 | ///
72 | public override IList Analyze(SqlRuleExecutionContext ruleExecutionContext)
73 | {
74 | List problems = new List();
75 | TSqlObject table = ruleExecutionContext.ModelElement;
76 | if (table != null)
77 | {
78 | if (NameEndsInView(table.Name))
79 | {
80 | // DisplayServices is a useful helper service for formatting names
81 | DisplayServices displayServices = ruleExecutionContext.SchemaModel.DisplayServices;
82 | string formattedName = displayServices.GetElementName(table, ElementNameStyle.FullyQualifiedName);
83 |
84 | string problemDescription = string.Format(NameEndingInViewMsgFormat,
85 | formattedName);
86 | SqlRuleProblem problem = new SqlRuleProblem(problemDescription, table);
87 | problems.Add(problem);
88 | }
89 | }
90 |
91 | return problems;
92 | }
93 |
94 | private bool NameEndsInView(ObjectIdentifier id)
95 | {
96 | return id.HasName && id.Parts.Last().EndsWith("View", StringComparison.OrdinalIgnoreCase);
97 | }
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/RuleSamples/WaitForDelayVisitor.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | //
4 | // The MIT License (MIT)
5 | //
6 | // Copyright (c) 2015 Microsoft
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 | //------------------------------------------------------------------------------
27 |
28 | using System.Collections.Generic;
29 | using Microsoft.SqlServer.TransactSql.ScriptDom;
30 |
31 | namespace Public.Dac.Samples.Rules
32 | {
33 | ///
34 | /// A TSqlConcreteFragmentVisitor allows us to examine an AST (abstract syntax tree) representation of a
35 | /// TSql object such as a Function, Procedure or Trigger. The implementation uses a visitor pattern, which traverses
36 | /// the logical tree structure of the object. For any type in the tree, the default unless you override it is to
37 | /// do nothing except examine its children. If you override one of the Visit methods it'll just let you examine
38 | /// objects of the type passes in as a parameter, and the visitor class will still automatically examine any children
39 | /// for that object. The ExplicitVisit methods control whether children are also visited so if you want to stop that from
40 | /// happening, you should override that method instead.
41 | ///
42 | /// Using a visitor can sometimes be much simpler than querying the object model, especially in the case where the concept
43 | /// you are trying to find isn't specifically related to a property or relationship in the model. That is true
44 | /// in this case, since we are looking to find any "WAITFOR" clause inside a Procedure, Function or Trigger and
45 | /// this isn't something you could query the Model API to find. As such it's a perfect example of when to examine the
46 | /// underlying structure of the object, rather than its basic set of properties and relationships.
47 | ///
48 | /// Side Note:
49 | /// Also note that the "WAITFOR" statement will be found inside the body script of a procedure/function/trigger.
50 | /// The body script is something of a special case in the model API since it's not queryable directly from the public model,
51 | /// and it can contain "dynamic" objects that aren't a part of the full model. What this means is that you can define temporary
52 | /// variables and objects in a procedure body, but these won't be queryable using the public model. If you wanted to identify problems
53 | /// with these dynamic objects you'd again have to check for them using a TSqlFragmentVisitor / TSqlConcreteFragmentVisitor since there's
54 | /// no way to find them using the Model APIs. However for objects that are defined elsewhere in the model you could check the
55 | /// Procedure.BodyDependencies relationship to see what the procedure's body references, and run some analysis based on this.
56 | ///
57 | ///
58 | internal class WaitForDelayVisitor : TSqlConcreteFragmentVisitor
59 | {
60 | public IList WaitForDelayStatements { get; private set; }
61 |
62 | public WaitForDelayVisitor()
63 | {
64 | WaitForDelayStatements = new List();
65 | }
66 |
67 | public override void ExplicitVisit(WaitForStatement node)
68 | {
69 | // We are only interested in WAITFOR DELAY occurrences
70 | if (node.WaitForOption == WaitForOption.Delay)
71 | {
72 | WaitForDelayStatements.Add(node);
73 | }
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/RuleSamples/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/RuleTests/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("RuleTests")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("RuleTests")]
13 | [assembly: AssemblyCopyright("Copyright © 2014")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("a914137f-f6f7-40a9-b41e-1975102348dd")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/RuleTests/RuleTestUtils.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | //
4 | // The MIT License (MIT)
5 | //
6 | // Copyright (c) 2015 Microsoft
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 | //------------------------------------------------------------------------------
27 |
28 | using System.IO;
29 |
30 | namespace Public.Dac.Samples.Rules.Tests
31 | {
32 | internal sealed class RuleTestUtils
33 | {
34 |
35 | public static void SaveStringToFile(string contents, string filename)
36 | {
37 | FileStream fileStream = null;
38 | StreamWriter streamWriter = null;
39 | try
40 | {
41 | string directory = Path.GetDirectoryName(filename);
42 | if (!Directory.Exists(directory))
43 | {
44 | Directory.CreateDirectory(directory);
45 | }
46 |
47 | fileStream = new FileStream(filename, FileMode.Create);
48 | streamWriter = new StreamWriter(fileStream);
49 | streamWriter.Write(contents);
50 | }
51 | finally
52 | {
53 | if (streamWriter != null)
54 | {
55 | streamWriter.Close();
56 | }
57 | if (fileStream != null)
58 | {
59 | fileStream.Close();
60 | }
61 | }
62 | }
63 |
64 | public static string ReadFileToString(string filePath)
65 | {
66 | using (StreamReader reader = new StreamReader(filePath))
67 | {
68 | return reader.ReadToEnd();
69 | }
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/RuleTests/TestScripts/AvoidWaitForDelayRule/AvoidWaitForDelayRule-Baseline.txt:
--------------------------------------------------------------------------------
1 | Problem description: WAITFOR DELAY statement was found in [dbo].[DatabaseScalarFunction1]
2 | FullID: Public.Dac.Samples.SR1004
3 | Severity: Warning
4 | Model element: dbo.DatabaseScalarFunction1
5 | Script file: DatabaseScalarFunction1.sql
6 | Start line: 9
7 | Start column: 5
8 | ========end of problem========
9 |
10 | Problem description: WAITFOR DELAY statement was found in [dbo].[ProcWithWaitForDelay]
11 | FullID: Public.Dac.Samples.SR1004
12 | Severity: Warning
13 | Model element: dbo.ProcWithWaitForDelay
14 | Script file: ProcWithWaitForDelay.sql
15 | Start line: 5
16 | Start column: 3
17 | ========end of problem========
18 |
19 | Problem description: WAITFOR DELAY statement was found in [ServerTrigger1]
20 | FullID: Public.Dac.Samples.SR1004
21 | Severity: Warning
22 | Model element: ServerTrigger1
23 | Script file: ServerTrigger1.sql
24 | Start line: 6
25 | Start column: 3
26 | ========end of problem========
27 |
28 | Problem description: WAITFOR DELAY statement was found in [dbo].[TableValuedFunctionWithWaitForDelay]
29 | FullID: Public.Dac.Samples.SR1004
30 | Severity: Warning
31 | Model element: dbo.TableValuedFunctionWithWaitForDelay
32 | Script file: TableValuedFunctionWithWaitForDelay.sql
33 | Start line: 13
34 | Start column: 5
35 | ========end of problem========
36 |
37 |
--------------------------------------------------------------------------------
/RuleTests/TestScripts/AvoidWaitForDelayRule/DatabaseScalarFunction1.sql:
--------------------------------------------------------------------------------
1 | CREATE FUNCTION [dbo].[DatabaseScalarFunction1]
2 | (
3 | @param1 int,
4 | @param2 int
5 | )
6 | RETURNS INT
7 | AS
8 | BEGIN
9 | WAITFOR DELAY '00:00:05'; -- This should be flagged as a problem
10 | RETURN @param1 + @param2
11 | END
12 |
--------------------------------------------------------------------------------
/RuleTests/TestScripts/AvoidWaitForDelayRule/InlineFunction.sql:
--------------------------------------------------------------------------------
1 | CREATE FUNCTION [dbo].[InlineFunction] -- Won't even be examined since it's an inlined function
2 | (
3 | @param1 int,
4 | @param2 char(5)
5 | )
6 | RETURNS TABLE AS RETURN
7 | (
8 | SELECT @param1 AS c1,
9 | @param2 AS c2
10 | )
11 |
--------------------------------------------------------------------------------
/RuleTests/TestScripts/AvoidWaitForDelayRule/ProcWithWaitForDelay.sql:
--------------------------------------------------------------------------------
1 |
2 | CREATE PROCEDURE ProcWithWaitForDelay
3 | AS
4 | BEGIN
5 | WAITFOR DELAY '00:00:15'; -- Waits 15 seconds before executing. This should be flagged as a problem
6 | RETURN SELECT * FROM dbo.Table1
7 |
8 | END
--------------------------------------------------------------------------------
/RuleTests/TestScripts/AvoidWaitForDelayRule/ProcWithWaitForTime.sql:
--------------------------------------------------------------------------------
1 |
2 | CREATE PROCEDURE ProcWithWaitForTime
3 | AS
4 | BEGIN
5 | WAITFOR TIME '00:00:15'; -- Executes at 15seconds after midnight. This shouldn't cause a problem
6 | RETURN SELECT * FROM dbo.Table1
7 |
8 | END
--------------------------------------------------------------------------------
/RuleTests/TestScripts/AvoidWaitForDelayRule/ServerTrigger1.sql:
--------------------------------------------------------------------------------
1 | CREATE TRIGGER [ServerTrigger1]
2 | ON ALL SERVER
3 | FOR LOGON
4 | AS
5 | BEGIN
6 | WAITFOR DELAY '00:00:05'; -- This should be flagged as a problem
7 | SET NOCOUNT ON
8 | END
9 |
--------------------------------------------------------------------------------
/RuleTests/TestScripts/AvoidWaitForDelayRule/Table1.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE [dbo].[Table1] (
2 | [C1] INT NOT NULL
3 | );
4 |
5 |
--------------------------------------------------------------------------------
/RuleTests/TestScripts/AvoidWaitForDelayRule/TableValuedFunctionWithWaitForDelay.sql:
--------------------------------------------------------------------------------
1 | CREATE FUNCTION [dbo].[TableValuedFunctionWithWaitForDelay]
2 | (
3 | @param1 int,
4 | @param2 char(5)
5 | )
6 | RETURNS @returntable TABLE
7 | (
8 | c1 int,
9 | c2 char(5)
10 | )
11 | AS
12 | BEGIN
13 | WAITFOR DELAY '00:00:05'; -- This should be flagged as a problem
14 | INSERT @returntable
15 | SELECT @param1, @param2
16 | RETURN
17 | END
18 |
--------------------------------------------------------------------------------
/RuleTests/TestScripts/README.txt:
--------------------------------------------------------------------------------
1 | When adding new test scripts (source files and baselines), you must ensure that you set the "Copy to Output Directory"
2 | property to "Copy Always". Otherwise they won't be found in the expected location when running our tests.
3 | To set this property, right-click on the file in Solution Explorer and choose "Properties". The options for the file will be
4 | visible in the Properties window once you do this.
--------------------------------------------------------------------------------
/RuleTests/TestScripts/TestBin2CollationOnProjectRule/Filegroup.sql:
--------------------------------------------------------------------------------
1 |
2 |
3 | /*
4 | Do not change the database path or name variables.
5 | Any sqlcmd variables will be properly substituted during
6 | build and deployment.
7 | */
8 |
9 | ALTER DATABASE [$(DatabaseName)]
10 | ADD FILEGROUP [Table1_FG] CONTAINS MEMORY_OPTIMIZED_DATA
--------------------------------------------------------------------------------
/RuleTests/TestScripts/TestBin2CollationOnProjectRule/TableWithBin2Collation.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Given indexes on a column with specific Bin2 collation, no problem should be found
3 | */
4 |
5 | CREATE TABLE [dbo].[TableWithBin2Collation]
6 | (
7 | [Id] INT NOT NULL PRIMARY KEY NONCLUSTERED HASH WITH (BUCKET_COUNT = 131072),
8 | [c2] nvarchar(30) COLLATE SQL_Latin1_General_CP850_BIN2 NOT NULL ,
9 | INDEX [IX_TableWithoutBin2Collation_Column] NONCLUSTERED HASH (c2) WITH (BUCKET_COUNT = 131072)
10 | ) WITH (MEMORY_OPTIMIZED = ON)
11 |
12 | GO
13 |
--------------------------------------------------------------------------------
/RuleTests/TestScripts/TestBin2CollationOnProjectRule/TableWithSpecificNonBin2Collation.sql:
--------------------------------------------------------------------------------
1 | /*
2 | If column has specific non-BIN2 collation a problem should be detected
3 | */
4 | CREATE TABLE [dbo].[TableWithSpecificNonBin2Collation]
5 | (
6 | [Id] INT NOT NULL PRIMARY KEY NONCLUSTERED HASH WITH (BUCKET_COUNT = 131072),
7 | [c2] nvarchar(30) COLLATE SQL_Latin1_General_CP1250_CS_AS NOT NULL ,
8 | INDEX [IX_TableWithSpecificNonBin2Collation_Column] NONCLUSTERED HASH (c2) WITH (BUCKET_COUNT = 131072)
9 | ) WITH (MEMORY_OPTIMIZED = ON)
10 |
11 | GO
12 |
--------------------------------------------------------------------------------
/RuleTests/TestScripts/TestBin2CollationOnProjectRule/TableWithoutBin2Collation.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Given the overall project has BIN2 collation, even character columns without a specific collation
3 | should be fine - no problems will be detected.
4 | */
5 |
6 | CREATE TABLE [dbo].[TableWithoutBin2Collation]
7 | (
8 | [Id] INT NOT NULL PRIMARY KEY NONCLUSTERED HASH WITH (BUCKET_COUNT = 131072),
9 | [c2] nvarchar(30) NOT NULL,
10 | [c3] varchar(30) NOT NULL,
11 | [c4] char(30) NOT NULL,
12 | [c5] nchar(30) NOT NULL,
13 | [cWithCollation] nchar(30) COLLATE SQL_Latin1_General_CP850_BIN2 NOT NULL,
14 | [int5] int NOT NULL,
15 | INDEX [IX_T1_C2] NONCLUSTERED HASH (c2) WITH (BUCKET_COUNT = 131072),
16 | INDEX [IX_T1_MultipleIndexes] NONCLUSTERED HASH (c3, c4) WITH (BUCKET_COUNT = 131072),
17 | INDEX [IX_T1_c5] NONCLUSTERED HASH (c5) WITH (BUCKET_COUNT = 131072),
18 | INDEX [IX_T1_int5] NONCLUSTERED HASH (int5) WITH (BUCKET_COUNT = 131072),
19 | INDEX [IX_T1_MultipleIndexesOneWithBin2] NONCLUSTERED HASH (c3, cWithCollation) WITH (BUCKET_COUNT = 131072),
20 | INDEX [IX_T1_MultipleIndexesAllValid] NONCLUSTERED HASH (cWithCollation, int5) WITH (BUCKET_COUNT = 131072)
21 | ) WITH (MEMORY_OPTIMIZED = ON)
22 |
23 | GO
--------------------------------------------------------------------------------
/RuleTests/TestScripts/TestBin2CollationOnProjectRule/TestBin2CollationOnProjectRule-Baseline.txt:
--------------------------------------------------------------------------------
1 | Problem description: Index [dbo].[TableWithSpecificNonBin2Collation].[IX_TableWithSpecificNonBin2Collation_Column] is on a character column [dbo].[TableWithSpecificNonBin2Collation].[c2] that does not use a *_BIN2 collation. This is not supported for indexes on memory optimized tables. The collation 'SQL_Latin1_General_CP1250_CS_AS' for the database or for the specified column should be changed
2 | FullID: Public.Dac.Samples.SR1101
3 | Severity: Warning
4 | Model element: dbo.TableWithSpecificNonBin2Collation.IX_TableWithSpecificNonBin2Collation_Column
5 | Script file: TableWithSpecificNonBin2Collation.sql
6 | Start line: 8
7 | Start column: 5
8 | ========end of problem========
9 |
10 | Problem description: Index [dbo].[TableWithUddts].[IX_TableWithUddts_C2] is on a character column [dbo].[TableWithUddts].[c2] that does not use a *_BIN2 collation. This is not supported for indexes on memory optimized tables. The collation 'SQL_Latin1_General_CP1250_CS_AS' for the database or for the specified column should be changed
11 | FullID: Public.Dac.Samples.SR1101
12 | Severity: Warning
13 | Model element: dbo.TableWithUddts.IX_TableWithUddts_C2
14 | Script file: UddtTests.sql
15 | Start line: 23
16 | Start column: 5
17 | ========end of problem========
18 |
19 |
--------------------------------------------------------------------------------
/RuleTests/TestScripts/TestBin2CollationOnProjectRule/UddtTests.sql:
--------------------------------------------------------------------------------
1 | CREATE TYPE [dbo].[CharDataType1]
2 | FROM varchar(11) NOT NULL
3 |
4 | GO
5 |
6 | CREATE TYPE [dbo].[CharDataType2]
7 | FROM nvarchar(25) NOT NULL
8 | GO
9 |
10 | CREATE TYPE [dbo].[IntDataType2]
11 | FROM int NOT NULL
12 |
13 | GO
14 |
15 |
16 | CREATE TABLE [dbo].[TableWithUddts]
17 | (
18 | [Id] IntDataType2 NOT NULL PRIMARY KEY NONCLUSTERED HASH WITH (BUCKET_COUNT = 131072),
19 | [c1] CharDataType1 NOT NULL,
20 | [c2] CharDataType2 COLLATE SQL_Latin1_General_CP1250_CS_AS NOT NULL,
21 | INDEX [IX_TableWithUddts_Id] NONCLUSTERED HASH (Id) WITH (BUCKET_COUNT = 222272),
22 | INDEX [IX_TableWithUddts_C1] NONCLUSTERED HASH (c1) WITH (BUCKET_COUNT = 131072),
23 | INDEX [IX_TableWithUddts_C2] NONCLUSTERED HASH (c2) WITH (BUCKET_COUNT = 131072),
24 | ) WITH (MEMORY_OPTIMIZED = ON)
--------------------------------------------------------------------------------
/RuleTests/TestScripts/TestCapitalizedNamesRule/TestCapitalizedNamesRule-Baseline.txt:
--------------------------------------------------------------------------------
1 | Problem description: '[dbo].[lowercasetable]' does not start with a capital letter. Lowercase names are not recommended
2 | FullID: Public.Dac.Samples.SR1103
3 | Severity: Warning
4 | Model element: dbo.lowercasetable
5 | Script file: TestScript.sql
6 | Start line: 6
7 | Start column: 14
8 | ========end of problem========
9 |
10 | Problem description: '[dbo].[lowercasetable].[c2]' does not start with a capital letter. Lowercase names are not recommended
11 | FullID: Public.Dac.Samples.SR1103
12 | Severity: Warning
13 | Model element: dbo.lowercasetable.c2
14 | Script file: TestScript.sql
15 | Start line: 11
16 | Start column: 5
17 | ========end of problem========
18 |
19 | Problem description: '[dbo].[lowercaseView]' does not start with a capital letter. Lowercase names are not recommended
20 | FullID: Public.Dac.Samples.SR1103
21 | Severity: Warning
22 | Model element: dbo.lowercaseView
23 | Script file: TestScript.sql
24 | Start line: 19
25 | Start column: 13
26 | ========end of problem========
27 |
28 | Problem description: '[dbo].[lowercaseView].[c2]' does not start with a capital letter. Lowercase names are not recommended
29 | FullID: Public.Dac.Samples.SR1103
30 | Severity: Warning
31 | Model element: dbo.lowercaseView.c2
32 | Script file: TestScript.sql
33 | Start line: 22
34 | Start column: 12
35 | ========end of problem========
36 |
37 | Problem description: '[dbo].[lowercaseView].[id]' does not start with a capital letter. Lowercase names are not recommended
38 | FullID: Public.Dac.Samples.SR1103
39 | Severity: Warning
40 | Model element: dbo.lowercaseView.id
41 | Script file: TestScript.sql
42 | Start line: 22
43 | Start column: 26
44 | ========end of problem========
45 |
46 | Problem description: '[dbo].[lowercaseProcedure]' does not start with a capital letter. Lowercase names are not recommended
47 | FullID: Public.Dac.Samples.SR1103
48 | Severity: Warning
49 | Model element: dbo.lowercaseProcedure
50 | Script file: TestScript.sql
51 | Start line: 26
52 | Start column: 18
53 | ========end of problem========
54 |
55 |
--------------------------------------------------------------------------------
/RuleTests/TestScripts/TestCapitalizedNamesRule/TestScript.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Given lowercase named objects expect problems to be detected.
3 | Note that since dbo is not user-defined it won't be flagged
4 | */
5 |
6 | CREATE TABLE [dbo].[lowercasetable]
7 | (
8 | -- Id capitalized: no problem even though table is not capitalized
9 | [Id] INT NOT NULL PRIMARY KEY NONCLUSTERED HASH WITH (BUCKET_COUNT = 131072),
10 | -- c2 lowercase: expect problem
11 | [c2] nvarchar(30) COLLATE SQL_Latin1_General_CP850_BIN2 NOT NULL,
12 |
13 | INDEX [IX_UPPERCASE] NONCLUSTERED HASH (c2) WITH (BUCKET_COUNT = 131072),
14 | ) WITH (MEMORY_OPTIMIZED = ON)
15 |
16 | GO
17 |
18 | -- v2, c2, id all should be flagged
19 | CREATE VIEW lowercaseView
20 | WITH SCHEMABINDING
21 | AS
22 | SELECT c2, c2 AS C3, Id as id FROM dbo.lowercasetable
23 | GO
24 |
25 | -- Procedure is flagged
26 | CREATE PROCEDURE [dbo].[lowercaseProcedure]
27 | -- Parameters will be not be flagged as they do not start with a letter or digit.
28 | @param1 int = 0,
29 | @param2 int
30 | AS
31 | SELECT @param1, @param2
32 | RETURN 0
33 |
34 | GO
35 | /*
36 |
37 | */
38 | /*
39 | Given capitalized or uppercase named expect no problems
40 | */
41 | CREATE TABLE [dbo].[CapitalizedTable]
42 | (
43 | [Id] INT NOT NULL PRIMARY KEY NONCLUSTERED HASH WITH (BUCKET_COUNT = 131072),
44 | [C2] nvarchar(30) COLLATE SQL_Latin1_General_CP850_BIN2 NOT NULL,
45 |
46 | INDEX [IX_UPPERCASE] NONCLUSTERED HASH (C2) WITH (BUCKET_COUNT = 131072),
47 | ) WITH (MEMORY_OPTIMIZED = ON)
48 |
49 | GO
50 |
51 | CREATE VIEW UPPERCASEVIEW AS
52 | SELECT C2, C2 AS C3 FROM [dbo].[CapitalizedTable]
53 |
54 | GO
55 |
56 | CREATE PROCEDURE [dbo].[CapitalizedProc]
57 | @Param1 int = 0,
58 | @Param2 int
59 | AS
60 | SELECT @Param1, @Param2
61 | RETURN 0
62 |
--------------------------------------------------------------------------------
/RuleTests/TestScripts/TestNonBin2CollationOnProjectRule/Filegroup.sql:
--------------------------------------------------------------------------------
1 |
2 |
3 | /*
4 | Do not change the database path or name variables.
5 | Any sqlcmd variables will be properly substituted during
6 | build and deployment.
7 | */
8 |
9 | ALTER DATABASE [$(DatabaseName)]
10 | ADD FILEGROUP [Table1_FG] CONTAINS MEMORY_OPTIMIZED_DATA
--------------------------------------------------------------------------------
/RuleTests/TestScripts/TestNonBin2CollationOnProjectRule/TableWithBin2Collation.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Given indexes on a column with specific Bin2 collation, no problem should be found
3 | */
4 |
5 | CREATE TABLE [dbo].[TableWithBin2Collation]
6 | (
7 | [Id] INT NOT NULL PRIMARY KEY NONCLUSTERED HASH WITH (BUCKET_COUNT = 131072),
8 | [c2] nvarchar(30) COLLATE SQL_Latin1_General_CP850_BIN2 NOT NULL ,
9 | INDEX [IX_TableWithoutBin2Collation_Column] NONCLUSTERED HASH (c2) WITH (BUCKET_COUNT = 131072)
10 | ) WITH (MEMORY_OPTIMIZED = ON)
11 |
12 | GO
13 |
--------------------------------------------------------------------------------
/RuleTests/TestScripts/TestNonBin2CollationOnProjectRule/TableWithSpecificNonBin2Collation.sql:
--------------------------------------------------------------------------------
1 | /*
2 | If column has specific non-BIN2 collation a problem should be detected
3 | */
4 | CREATE TABLE [dbo].[TableWithSpecificNonBin2Collation]
5 | (
6 | [Id] INT NOT NULL PRIMARY KEY NONCLUSTERED HASH WITH (BUCKET_COUNT = 131072),
7 | [c2] nvarchar(30) COLLATE SQL_Latin1_General_CP1250_CS_AS NOT NULL ,
8 | INDEX [IX_TableWithSpecificNonBin2Collation_Column] NONCLUSTERED HASH (c2) WITH (BUCKET_COUNT = 131072)
9 | ) WITH (MEMORY_OPTIMIZED = ON)
10 |
11 | GO
12 |
--------------------------------------------------------------------------------
/RuleTests/TestScripts/TestNonBin2CollationOnProjectRule/TableWithoutBin2Collation.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Given the project has a non-BIN2 collation, any indexes on character columns without a specific, BIN2 collation
3 | should cause errors to be raised
4 | */
5 |
6 | CREATE TABLE [dbo].[TableWithoutBin2Collation]
7 | (
8 | [Id] INT NOT NULL PRIMARY KEY NONCLUSTERED HASH WITH (BUCKET_COUNT = 131072),
9 | [c2] nvarchar(30) NOT NULL,
10 | [c3] varchar(30) NOT NULL,
11 | [c4] char(30) NOT NULL,
12 | [c5] nchar(30) NOT NULL,
13 | [cWithCollation] nchar(30) COLLATE SQL_Latin1_General_CP850_BIN2 NOT NULL,
14 | [int5] int NOT NULL,
15 | INDEX [IX_T1_C2] NONCLUSTERED HASH (c2) WITH (BUCKET_COUNT = 131072),
16 | INDEX [IX_T1_MultipleIndexes] NONCLUSTERED HASH (c3, c4) WITH (BUCKET_COUNT = 131072),
17 | INDEX [IX_T1_c5] NONCLUSTERED HASH (c5) WITH (BUCKET_COUNT = 131072),
18 | INDEX [IX_T1_int5] NONCLUSTERED HASH (int5) WITH (BUCKET_COUNT = 131072),
19 | INDEX [IX_T1_MultipleIndexesOneWithBin2] NONCLUSTERED HASH (c3, cWithCollation) WITH (BUCKET_COUNT = 131072),
20 | INDEX [IX_T1_MultipleIndexesAllValid] NONCLUSTERED HASH (cWithCollation, int5) WITH (BUCKET_COUNT = 131072)
21 | ) WITH (MEMORY_OPTIMIZED = ON)
22 |
23 | GO
--------------------------------------------------------------------------------
/RuleTests/TestScripts/TestNonBin2CollationOnProjectRule/TestNonBin2CollationOnProjectRule-Baseline.txt:
--------------------------------------------------------------------------------
1 | Problem description: Index [dbo].[TableWithoutBin2Collation].[IX_T1_C2] is on a character column [dbo].[TableWithoutBin2Collation].[c2] that does not use a *_BIN2 collation. This is not supported for indexes on memory optimized tables. The collation 'SQL_Latin1_General_CP1_CI_AS' for the database or for the specified column should be changed
2 | FullID: Public.Dac.Samples.SR1101
3 | Severity: Warning
4 | Model element: dbo.TableWithoutBin2Collation.IX_T1_C2
5 | Script file: TableWithoutBin2Collation.sql
6 | Start line: 15
7 | Start column: 5
8 | ========end of problem========
9 |
10 | Problem description: Index [dbo].[TableWithoutBin2Collation].[IX_T1_MultipleIndexes] is on a character column [dbo].[TableWithoutBin2Collation].[c3] that does not use a *_BIN2 collation. This is not supported for indexes on memory optimized tables. The collation 'SQL_Latin1_General_CP1_CI_AS' for the database or for the specified column should be changed
11 | FullID: Public.Dac.Samples.SR1101
12 | Severity: Warning
13 | Model element: dbo.TableWithoutBin2Collation.IX_T1_MultipleIndexes
14 | Script file: TableWithoutBin2Collation.sql
15 | Start line: 16
16 | Start column: 5
17 | ========end of problem========
18 |
19 | Problem description: Index [dbo].[TableWithoutBin2Collation].[IX_T1_MultipleIndexes] is on a character column [dbo].[TableWithoutBin2Collation].[c4] that does not use a *_BIN2 collation. This is not supported for indexes on memory optimized tables. The collation 'SQL_Latin1_General_CP1_CI_AS' for the database or for the specified column should be changed
20 | FullID: Public.Dac.Samples.SR1101
21 | Severity: Warning
22 | Model element: dbo.TableWithoutBin2Collation.IX_T1_MultipleIndexes
23 | Script file: TableWithoutBin2Collation.sql
24 | Start line: 16
25 | Start column: 5
26 | ========end of problem========
27 |
28 | Problem description: Index [dbo].[TableWithoutBin2Collation].[IX_T1_c5] is on a character column [dbo].[TableWithoutBin2Collation].[c5] that does not use a *_BIN2 collation. This is not supported for indexes on memory optimized tables. The collation 'SQL_Latin1_General_CP1_CI_AS' for the database or for the specified column should be changed
29 | FullID: Public.Dac.Samples.SR1101
30 | Severity: Warning
31 | Model element: dbo.TableWithoutBin2Collation.IX_T1_c5
32 | Script file: TableWithoutBin2Collation.sql
33 | Start line: 17
34 | Start column: 5
35 | ========end of problem========
36 |
37 | Problem description: Index [dbo].[TableWithoutBin2Collation].[IX_T1_MultipleIndexesOneWithBin2] is on a character column [dbo].[TableWithoutBin2Collation].[c3] that does not use a *_BIN2 collation. This is not supported for indexes on memory optimized tables. The collation 'SQL_Latin1_General_CP1_CI_AS' for the database or for the specified column should be changed
38 | FullID: Public.Dac.Samples.SR1101
39 | Severity: Warning
40 | Model element: dbo.TableWithoutBin2Collation.IX_T1_MultipleIndexesOneWithBin2
41 | Script file: TableWithoutBin2Collation.sql
42 | Start line: 19
43 | Start column: 5
44 | ========end of problem========
45 |
46 | Problem description: Index [dbo].[TableWithSpecificNonBin2Collation].[IX_TableWithSpecificNonBin2Collation_Column] is on a character column [dbo].[TableWithSpecificNonBin2Collation].[c2] that does not use a *_BIN2 collation. This is not supported for indexes on memory optimized tables. The collation 'SQL_Latin1_General_CP1250_CS_AS' for the database or for the specified column should be changed
47 | FullID: Public.Dac.Samples.SR1101
48 | Severity: Warning
49 | Model element: dbo.TableWithSpecificNonBin2Collation.IX_TableWithSpecificNonBin2Collation_Column
50 | Script file: TableWithSpecificNonBin2Collation.sql
51 | Start line: 8
52 | Start column: 5
53 | ========end of problem========
54 |
55 | Problem description: Index [dbo].[TableWithUddts].[IX_TableWithUddts_C1] is on a character column [dbo].[TableWithUddts].[c1] that does not use a *_BIN2 collation. This is not supported for indexes on memory optimized tables. The collation 'SQL_Latin1_General_CP1_CI_AS' for the database or for the specified column should be changed
56 | FullID: Public.Dac.Samples.SR1101
57 | Severity: Warning
58 | Model element: dbo.TableWithUddts.IX_TableWithUddts_C1
59 | Script file: UddtTests.sql
60 | Start line: 22
61 | Start column: 5
62 | ========end of problem========
63 |
64 | Problem description: Index [dbo].[TableWithUddts].[IX_TableWithUddts_C2] is on a character column [dbo].[TableWithUddts].[c2] that does not use a *_BIN2 collation. This is not supported for indexes on memory optimized tables. The collation 'SQL_Latin1_General_CP1250_CS_AS' for the database or for the specified column should be changed
65 | FullID: Public.Dac.Samples.SR1101
66 | Severity: Warning
67 | Model element: dbo.TableWithUddts.IX_TableWithUddts_C2
68 | Script file: UddtTests.sql
69 | Start line: 23
70 | Start column: 5
71 | ========end of problem========
72 |
73 |
--------------------------------------------------------------------------------
/RuleTests/TestScripts/TestNonBin2CollationOnProjectRule/UddtTests.sql:
--------------------------------------------------------------------------------
1 | CREATE TYPE [dbo].[CharDataType1]
2 | FROM varchar(11) NOT NULL
3 |
4 | GO
5 |
6 | CREATE TYPE [dbo].[CharDataType2]
7 | FROM nvarchar(25) NOT NULL
8 | GO
9 |
10 | CREATE TYPE [dbo].[IntDataType2]
11 | FROM int NOT NULL
12 |
13 | GO
14 |
15 |
16 | CREATE TABLE [dbo].[TableWithUddts]
17 | (
18 | [Id] IntDataType2 NOT NULL PRIMARY KEY NONCLUSTERED HASH WITH (BUCKET_COUNT = 131072),
19 | [c1] CharDataType1 NOT NULL,
20 | [c2] CharDataType2 COLLATE SQL_Latin1_General_CP1250_CS_AS NOT NULL,
21 | INDEX [IX_TableWithUddts_Id] NONCLUSTERED HASH (Id) WITH (BUCKET_COUNT = 222272),
22 | INDEX [IX_TableWithUddts_C1] NONCLUSTERED HASH (c1) WITH (BUCKET_COUNT = 131072),
23 | INDEX [IX_TableWithUddts_C2] NONCLUSTERED HASH (c2) WITH (BUCKET_COUNT = 131072),
24 | ) WITH (MEMORY_OPTIMIZED = ON)
--------------------------------------------------------------------------------
/RuleTests/TestScripts/TestViewOnMemoryOptimizedTableRule/Filegroup.sql:
--------------------------------------------------------------------------------
1 |
2 |
3 | /*
4 | Do not change the database path or name variables.
5 | Any sqlcmd variables will be properly substituted during
6 | build and deployment.
7 | */
8 |
9 | ALTER DATABASE [$(DatabaseName)]
10 | ADD FILEGROUP [Table1_FG] CONTAINS MEMORY_OPTIMIZED_DATA
--------------------------------------------------------------------------------
/RuleTests/TestScripts/TestViewOnMemoryOptimizedTableRule/Table1.sql:
--------------------------------------------------------------------------------
1 | -- Memory optimized table
2 | CREATE TABLE [dbo].[Table1]
3 | (
4 | [Id] INT NOT NULL PRIMARY KEY NONCLUSTERED HASH WITH (BUCKET_COUNT = 131072),
5 | [c2] nvarchar(30) NOT NULL,
6 | INDEX [IX_Table1_Column] NONCLUSTERED HASH (c2) WITH (BUCKET_COUNT = 131072)
7 | ) WITH (MEMORY_OPTIMIZED = ON)
8 |
9 | GO
--------------------------------------------------------------------------------
/RuleTests/TestScripts/TestViewOnMemoryOptimizedTableRule/Table2.sql:
--------------------------------------------------------------------------------
1 | -- standard table
2 | CREATE TABLE [dbo].[Table2] (
3 | [Id] INT NOT NULL,
4 | PRIMARY KEY CLUSTERED ([Id] ASC),
5 | CONSTRAINT [CK_Table_Column2] CHECK ((2)=(2))
6 | );
7 |
8 | GO
9 | ALTER TABLE [dbo].[Table2] ADD CONSTRAINT [CK_Table_Column] CHECK ((1)=(1))
10 |
11 | GO
12 | CREATE NONCLUSTERED INDEX [IX_Table_Column]
13 | ON [dbo].[Table2]([Id] ASC);
14 |
15 |
--------------------------------------------------------------------------------
/RuleTests/TestScripts/TestViewOnMemoryOptimizedTableRule/TestViewOnMemoryOptimizedTableRule-Baseline.txt:
--------------------------------------------------------------------------------
1 | Problem description: View [dbo].[View1] must specify the 'WITH SCHEMABINDING' view attribute as it references a memory optimized table [dbo].[Table1]
2 | FullID: Public.Dac.Samples.SR1102
3 | Severity: Warning
4 | Model element: dbo.View1
5 | Script file: View1Tests.sql
6 | Start line: 1
7 | Start column: 13
8 | ========end of problem========
9 |
10 | Problem description: The index [dbo].[View1].[IX_View1_myCol] on view [dbo].[View1] is not allowed, as the view references a memory optimized table [dbo].[Table1]
11 | FullID: Public.Dac.Samples.SR1102
12 | Severity: Warning
13 | Model element: dbo.View1.IX_View1_myCol
14 | Script file: View1Tests.sql
15 | Start line: 7
16 | Start column: 31
17 | ========end of problem========
18 |
19 | Problem description: The index [dbo].[View1].[IX_View1_c2] on view [dbo].[View1] is not allowed, as the view references a memory optimized table [dbo].[Table1]
20 | FullID: Public.Dac.Samples.SR1102
21 | Severity: Warning
22 | Model element: dbo.View1.IX_View1_c2
23 | Script file: View1Tests.sql
24 | Start line: 10
25 | Start column: 14
26 | ========end of problem========
27 |
28 |
--------------------------------------------------------------------------------
/RuleTests/TestScripts/TestViewOnMemoryOptimizedTableRule/View1Tests.sql:
--------------------------------------------------------------------------------
1 | CREATE VIEW [dbo].[View1]
2 | -- missing WITH SCHEMABINDING attribute
3 | AS SELECT T1.c2, T2.Id as myCol FROM [dbo].[Table1] as T1, [dbo].[Table2] as T2
4 | GO
5 |
6 | -- Indexes aren't allowed on this table
7 | CREATE UNIQUE CLUSTERED INDEX [IX_View1_myCol] on [dbo].[View1] (myCol)
8 | GO
9 |
10 | CREATE INDEX [IX_View1_c2] on [dbo].[View1] (c2)
11 | GO
12 |
13 | -- Valid View: Creating a view on Table1 should be OK if it specified schema binding
14 | CREATE VIEW [dbo].[View2]
15 | WITH SCHEMABINDING
16 | AS SELECT T1.c2, T2.Id as myCol FROM [dbo].[Table1] as T1, [dbo].Table2 as T2
17 | GO
18 |
19 | -- Valid Indexes: Creating indexes on views that don't reference memory optimized tables is acceptable
20 | CREATE VIEW [dbo].[View3]
21 | WITH SCHEMABINDING
22 | AS SELECT T2.Id as myCol FROM [dbo].Table2 as T2
23 | GO
24 | CREATE UNIQUE CLUSTERED INDEX [IX_View3_myCol] on [dbo].[View3] (myCol)
25 | GO
26 |
--------------------------------------------------------------------------------
/RuleTests/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Security
4 |
5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
6 |
7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.
8 |
9 | ## Reporting Security Issues
10 |
11 | **Please do not report security vulnerabilities through public GitHub issues.**
12 |
13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
14 |
15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).
16 |
17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc).
18 |
19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
20 |
21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
22 | * Full paths of source file(s) related to the manifestation of the issue
23 | * The location of the affected source code (tag/branch/commit or direct URL)
24 | * Any special configuration required to reproduce the issue
25 | * Step-by-step instructions to reproduce the issue
26 | * Proof-of-concept or exploit code (if possible)
27 | * Impact of the issue, including how an attacker might exploit the issue
28 |
29 | This information will help us triage your report more quickly.
30 |
31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.
32 |
33 | ## Preferred Languages
34 |
35 | We prefer all communications to be in English.
36 |
37 | ## Policy
38 |
39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).
40 |
41 |
42 |
--------------------------------------------------------------------------------
/SampleConsoleApp/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/SampleConsoleApp/ModelEndToEnd.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | //
4 | // The MIT License (MIT)
5 | //
6 | // Copyright (c) 2015 Microsoft
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 | //------------------------------------------------------------------------------
27 | using Microsoft.SqlServer.Dac;
28 | using Microsoft.SqlServer.Dac.Model;
29 | using Microsoft.SqlServer.TransactSql.ScriptDom;
30 | using System;
31 | using System.IO;
32 | using System.Linq;
33 | using ColumnType = Microsoft.SqlServer.Dac.Model.ColumnType;
34 |
35 | namespace Public.Dac.Samples.App
36 | {
37 | ///
38 | /// Basic demo class showing end to end usage of the model
39 | ///
40 | internal class ModelEndToEnd
41 | {
42 | public static void Run()
43 | {
44 | string dacpacPath = "relativePath.dacpac";
45 |
46 | // Note that you could read scripts from a file or use TSqlScript objects that are taken from other models.
47 | // Hand-crafting TSqlScript is quite awkard but could be done programmatically (we do it internally).
48 | // If you need examples for this let us know and we can look into that too.
49 | string[] scripts = new[]
50 | {
51 | "CREATE TABLE t1 (c1 NVARCHAR(30) NOT NULL)",
52 | "CREATE TABLE t2 (c2 INT NOT NULL)",
53 | "CREATE TABLE t3 (c3 INT NOT NULL)",
54 | "CREATE TABLE t4 (c4 INT NOT NULL)",
55 | };
56 | using (TSqlModel model = new TSqlModel(SqlServerVersion.Sql110, new TSqlModelOptions { }))
57 | {
58 | // Adding objects to the model.
59 | foreach (string script in scripts)
60 | {
61 | model.AddObjects(script);
62 | }
63 |
64 | ReadTheModel(model);
65 |
66 | CopyFromTheModel(model);
67 |
68 | // save the model to a new .dacpac
69 | // Note that the PackageOptions can be used to specify RefactorLog and contributors to include
70 | DacPackageExtensions.BuildPackage(
71 | dacpacPath,
72 | model,
73 | new PackageMetadata { Name = "MyPackageName", Description = "This is usually ignored", Version = "1.0" },
74 | new PackageOptions()
75 | );
76 | }
77 |
78 | // Load from a dacpac
79 | using (TSqlModel modelFromDacpac = new TSqlModel(dacpacPath))
80 | {
81 | // Show that all the elements were saved successfully
82 | ReadTheModel(modelFromDacpac);
83 |
84 | // You can update the model in the dacpac. Other parts of a dacpac can't be updated yet (pre/post deployment scripts)
85 | modelFromDacpac.AddObjects("CREATE VIEW V1 AS SELECT * FROM T1");
86 |
87 | using (DacPackage dacPackage = DacPackage.Load(dacpacPath,
88 | DacSchemaModelStorageType.Memory,
89 | FileAccess.ReadWrite))
90 | {
91 | DacPackageExtensions.UpdateModel(dacPackage, modelFromDacpac, null);
92 | }
93 | }
94 |
95 | Console.WriteLine("Press any key to finish");
96 | Console.ReadKey();
97 | }
98 |
99 | private static void ReadTheModel(TSqlModel model)
100 | {
101 | // This will get all tables.
102 | var tables = model.GetObjects(DacQueryScopes.Default, Table.TypeClass).ToList();
103 |
104 | // Look up a specific table by ID. Note that if no schema is defined when creating an element, the default "dbo" schema is used
105 | var t1 = model.GetObjects(Table.TypeClass, new ObjectIdentifier("dbo", "t1"), DacQueryScopes.UserDefined).FirstOrDefault();
106 |
107 | // Get a the column referenced by this table, and query its length
108 | TSqlObject column = t1.GetReferenced(Table.Columns).First(col => col.Name.Parts[2].Equals("c1"));
109 | int columnLength = column.GetProperty(Column.Length);
110 | Console.WriteLine("Column c1 has length {0}", columnLength);
111 |
112 | // Verify the ColumnType of this column. This can help indicate which properties will return meaningful values.
113 | // For instance since Column.Collation is only available on a simple column, and Column.Persisted is only on computed columns
114 | ColumnType columnType = column.GetMetadata(Column.ColumnType);
115 | Console.WriteLine("Column c1 is of type '{0}'", columnType);
116 | }
117 |
118 | private static void CopyFromTheModel(TSqlModel model)
119 | {
120 | // Copy all tables from 1 model to another - could be useful for filtering, say when you load from 1 model
121 | // And copy to another
122 | using (TSqlModel copiedModel = new TSqlModel(SqlServerVersion.Sql110, null))
123 | {
124 | foreach (var table in model.GetObjects(DacQueryScopes.Default, Table.TypeClass))
125 | {
126 | TSqlScript script;
127 | if (table.TryGetAst(out script))
128 | {
129 | copiedModel.AddObjects(script);
130 | }
131 | }
132 | }
133 | }
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/SampleConsoleApp/Program.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | //
4 | // The MIT License (MIT)
5 | //
6 | // Copyright (c) 2015 Microsoft
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 | //------------------------------------------------------------------------------
27 | using System;
28 |
29 | namespace Public.Dac.Samples.App
30 | {
31 | class Program
32 | {
33 | internal enum Behavior
34 | {
35 | Usage,
36 | RunEndToEnd,
37 | FilterModel,
38 | RunCodeAnalysis,
39 | ValidateQuerySemantically
40 | }
41 |
42 | static void Main(string[] args)
43 | {
44 |
45 | switch (GetBehavior(args))
46 | {
47 | case Behavior.Usage:
48 | Console.WriteLine(@"Specify the action you wish to perform, for example 'ModelBuilderApp.exe RunEndToEnd'
49 | Current actions:
50 | [RunEndToEnd] - Runs the end to end demo that creates a model, copies to another model, and saves the model to a dacpac
51 | [FilterModel] - Runs a demo that creates a model then creates a filtered copy with some schemas removed.
52 | [RunCodeAnalysis] - Runs a demo of running Static Code Analysis from your code.
53 | [Usage] - Print this usage message
54 | ");
55 | break;
56 | case Behavior.RunEndToEnd:
57 | ModelEndToEnd.Run();
58 | break;
59 | case Behavior.FilterModel:
60 | ModelFilterExample.RunFilteringExample();
61 | break;
62 | case Behavior.RunCodeAnalysis:
63 | RunCodeAnalysisExample.RunAnalysisExample();
64 | break;
65 | case Behavior.ValidateQuerySemantically:
66 | RunValidateQuerySemanticallyExample.Run();
67 | break;
68 | // To test deployment plan-based filtering see the TestFiltering.TestFilterPlanWhenPublishing() unit test
69 | }
70 |
71 | Console.WriteLine("Press any key to finish");
72 | Console.ReadKey();
73 | }
74 |
75 | private static Behavior GetBehavior(string[] args)
76 | {
77 | Behavior behavior = Behavior.Usage;
78 | if (args.Length > 0)
79 | {
80 | if (MatchesBehavior(args[0], Behavior.RunEndToEnd))
81 | {
82 | behavior = Behavior.RunEndToEnd;
83 | }
84 | if (MatchesBehavior(args[0], Behavior.FilterModel))
85 | {
86 | behavior = Behavior.FilterModel;
87 | }
88 | if (MatchesBehavior(args[0], Behavior.RunCodeAnalysis))
89 | {
90 | behavior = Behavior.RunCodeAnalysis;
91 | }
92 | if (MatchesBehavior(args[0], Behavior.ValidateQuerySemantically))
93 | {
94 | behavior = Behavior.ValidateQuerySemantically;
95 | }
96 | }
97 | return behavior;
98 | }
99 |
100 | private static bool MatchesBehavior(string name, Behavior behavior)
101 | {
102 | return string.Compare(name, behavior.ToString(), StringComparison.OrdinalIgnoreCase) == 0;
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/SampleConsoleApp/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | //
4 | // The MIT License (MIT)
5 | //
6 | // Copyright (c) 2015 Microsoft
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 | //------------------------------------------------------------------------------
27 | using System.Reflection;
28 | using System.Runtime.CompilerServices;
29 | using System.Runtime.InteropServices;
30 |
31 | // General Information about an assembly is controlled through the following
32 | // set of attributes. Change these attribute values to modify the information
33 | // associated with an assembly.
34 | [assembly: AssemblyTitle("ModelBuilderApp")]
35 | [assembly: AssemblyDescription("")]
36 | [assembly: AssemblyConfiguration("")]
37 | [assembly: AssemblyCompany("")]
38 | [assembly: AssemblyProduct("ModelBuilderApp")]
39 | [assembly: AssemblyCopyright("Copyright © 2013")]
40 | [assembly: AssemblyTrademark("")]
41 | [assembly: AssemblyCulture("")]
42 |
43 | // Setting ComVisible to false makes the types in this assembly not visible
44 | // to COM components. If you need to access a type in this assembly from
45 | // COM, set the ComVisible attribute to true on that type.
46 | [assembly: ComVisible(false)]
47 |
48 | // The following GUID is for the ID of the typelib if this project is exposed to COM
49 | [assembly: Guid("33997024-206a-4456-81ba-3bb0f1564126")]
50 |
51 | // Version information for an assembly consists of the following four values:
52 | //
53 | // Major Version
54 | // Minor Version
55 | // Build Number
56 | // Revision
57 | //
58 | // You can specify all the values or you can default the Build and Revision Numbers
59 | // by using the '*' as shown below:
60 | // [assembly: AssemblyVersion("1.0.*")]
61 | [assembly: AssemblyVersion("1.0.0.0")]
62 | [assembly: AssemblyFileVersion("1.0.0.0")]
63 |
--------------------------------------------------------------------------------
/SampleConsoleApp/RunValidateQuerySemanticallyExample.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | //
4 | // The MIT License (MIT)
5 | //
6 | // Copyright (c) 2015 Microsoft
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 | //------------------------------------------------------------------------------
27 | using System;
28 | using System.Collections.Generic;
29 | using System.Globalization;
30 | using System.Linq;
31 | using Microsoft.SqlServer.Dac;
32 | using Microsoft.SqlServer.Dac.Model;
33 | using Public.Dac.Samples.TestUtilities;
34 |
35 | namespace Public.Dac.Samples.App
36 | {
37 | public class RunValidateQuerySemanticallyExample
38 | {
39 |
40 | private static readonly string[] SampleScripts = new string[]
41 | {
42 | "CREATE TABLE T1 (c1 int)",
43 | @"CREATE VIEW [dbo].[View1] AS SELECT * FROM [dbo].[T1]",
44 | };
45 |
46 | ///
47 | /// DacFx is smart enough to realize there's a column c1 projected through View1 from T1
48 | ///
49 | private const string GoodQuery = "SELECT c1 from View1";
50 | ///
51 | /// DacFx will complain since the relevant column does not exist
52 | ///
53 | private const string BadQuery = @"SELECT c2 from View1";
54 |
55 | private const string ProcTemplate = @"CREATE PROCEDURE [NameThatNeverExistsInDb] AS BEGIN {0} END";
56 | public static void Run()
57 | {
58 | Console.WriteLine("Publishing scripts to DB");
59 | using (SqlTestDB db = TestUtils.CreateTestDatabase(TestUtils.DefaultInstanceInfo, "MyQueryExample"))
60 | {
61 | // set up the database with your scripts
62 | TestUtils.ExecuteNonQuery(db, SampleScripts);
63 |
64 | ValidateQuery(BadQuery, db, false);
65 |
66 | // BUG: Normally AddOrUpdateObjects will replace the contents of a file so we could just update the contents of our "Query File"
67 | // and re-run validation. This simulates live validation of a query in SSMS/SSDT.
68 | // Somehow when loading model directly from Database this isn't working. We will resolve this issue in a future DacFx update.
69 | // For now we create a new model for each query which is inefficient but relatively effective.
70 | ValidateQuery(GoodQuery, db, true);
71 | }
72 | }
73 |
74 | public static void ValidateQuery(string query, SqlTestDB db, bool expectQueryToPass)
75 | {
76 | Console.WriteLine("Testing query '{0}'", query);
77 | Console.WriteLine("Loading model from DB");
78 | using (TSqlModel model = TSqlModel.LoadFromDatabase(db.BuildConnectionString()))
79 | {
80 | // Currently we just give a message but no source information. Will work around this for now by ensuring the model is fully valid before proceeding
81 | bool modelInitiallyValid = PrintModelState(model, true);
82 | if (!modelInitiallyValid)
83 | {
84 | Console.WriteLine("Quitting due to invalid model");
85 | return;
86 | }
87 | AssertModelHasNProcedures(model, 0);
88 |
89 | string myFileName = "QueryFile.sql";
90 |
91 | // validate bad query fails validation
92 | model.AddOrUpdateObjects(CreateQueryAsProc(query), myFileName, null);
93 | PrintModelState(model, expectQueryToPass);
94 |
95 | AssertModelHasNProcedures(model, 1);
96 | }
97 | }
98 |
99 |
100 | private static void AssertModelHasNProcedures(TSqlModel model, int numProcs)
101 | {
102 | IEnumerable procs = model.GetObjects(DacQueryScopes.UserDefined, ModelSchema.Procedure);
103 | if(numProcs != procs.Count())
104 | {
105 | throw new Exception("Incorrect number of elements. Expected " + numProcs + " proc(s)");
106 | }
107 | }
108 |
109 |
110 | private static string CreateQueryAsProc(string query)
111 | {
112 | return string.Format(CultureInfo.CurrentCulture, ProcTemplate, query);
113 | }
114 |
115 | private static bool PrintModelState(TSqlModel model, bool expectQueryToPass)
116 | {
117 |
118 | string errorMessage = expectQueryToPass ? "Fail: Expected no issues but got the following:" : "Pass: expected issues found during validation:";
119 | string passMessage = expectQueryToPass ? "Pass: No problems found during validation" : "Fail: expected issues but none were found";
120 | bool breakingIssuesFound = false;
121 | var validationMessages = model.Validate();
122 | if (validationMessages.Count > 0)
123 | {
124 | Console.WriteLine(errorMessage);
125 | foreach (var message in validationMessages)
126 | {
127 | Console.WriteLine("\t" + message.Message);
128 | breakingIssuesFound = breakingIssuesFound || message.MessageType == DacMessageType.Error;
129 | }
130 | return false;
131 | }
132 | else
133 | {
134 | Console.WriteLine(passMessage);
135 | return true;
136 | }
137 |
138 | }
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/SampleConsoleApp/SampleConsoleApp.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {7855389B-A1F0-4A7C-A83A-38EEF5B73F9A}
8 | Exe
9 | Properties
10 | Public.Dac.Samples.App
11 | SampleConsoleApp
12 | v4.6
13 | 512
14 |
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | AnyCPU
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 |
37 | ..\packages\Microsoft.SqlServer.DacFx.x64.150.4826.1\lib\net46\Microsoft.Data.Tools.Schema.Sql.dll
38 |
39 |
40 | ..\packages\Microsoft.SqlServer.DacFx.x64.150.4826.1\lib\net46\Microsoft.Data.Tools.Utilities.dll
41 |
42 |
43 | ..\packages\Microsoft.SqlServer.DacFx.x64.150.4826.1\lib\net46\Microsoft.SqlServer.Dac.dll
44 |
45 |
46 | ..\packages\Microsoft.SqlServer.DacFx.x64.150.4826.1\lib\net46\Microsoft.SqlServer.Dac.Extensions.dll
47 |
48 |
49 | ..\packages\Microsoft.SqlServer.DacFx.x64.150.4826.1\lib\net46\Microsoft.SqlServer.TransactSql.ScriptDom.dll
50 |
51 |
52 | ..\packages\Microsoft.SqlServer.DacFx.x64.150.4826.1\lib\net46\Microsoft.SqlServer.Types.dll
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 | {c1c2b521-22b6-4124-aaec-a5e1fcab0dfa}
77 | Samples
78 |
79 |
80 | {edf01d79-66d0-496c-82d2-431831564817}
81 | TestUtils
82 |
83 |
84 |
85 |
92 |
--------------------------------------------------------------------------------
/SampleConsoleApp/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/SampleTests/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | //
4 | // The MIT License (MIT)
5 | //
6 | // Copyright (c) 2015 Microsoft
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 | //------------------------------------------------------------------------------
27 | using System.Reflection;
28 | using System.Runtime.CompilerServices;
29 | using System.Runtime.InteropServices;
30 |
31 | // General Information about an assembly is controlled through the following
32 | // set of attributes. Change these attribute values to modify the information
33 | // associated with an assembly.
34 | [assembly: AssemblyTitle("SampleTests")]
35 | [assembly: AssemblyDescription("")]
36 | [assembly: AssemblyConfiguration("")]
37 | [assembly: AssemblyCompany("")]
38 | [assembly: AssemblyProduct("SampleTests")]
39 | [assembly: AssemblyCopyright("Copyright © 2013")]
40 | [assembly: AssemblyTrademark("")]
41 | [assembly: AssemblyCulture("")]
42 |
43 | // Setting ComVisible to false makes the types in this assembly not visible
44 | // to COM components. If you need to access a type in this assembly from
45 | // COM, set the ComVisible attribute to true on that type.
46 | [assembly: ComVisible(false)]
47 |
48 | // The following GUID is for the ID of the typelib if this project is exposed to COM
49 | [assembly: Guid("8c5b9dfc-8136-43b2-9626-7277d5a3fd9b")]
50 |
51 | // Version information for an assembly consists of the following four values:
52 | //
53 | // Major Version
54 | // Minor Version
55 | // Build Number
56 | // Revision
57 | //
58 | // You can specify all the values or you can default the Build and Revision Numbers
59 | // by using the '*' as shown below:
60 | // [assembly: AssemblyVersion("1.0.*")]
61 | [assembly: AssemblyVersion("1.0.0.0")]
62 | [assembly: AssemblyFileVersion("1.0.0.0")]
63 |
--------------------------------------------------------------------------------
/SampleTests/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Samples/CompositeFilter.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | //
4 | // The MIT License (MIT)
5 | //
6 | // Copyright (c) 2015 Microsoft
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 | //------------------------------------------------------------------------------
27 | using System.Collections.Generic;
28 | using Microsoft.SqlServer.Dac.Model;
29 |
30 | namespace Public.Dac.Samples
31 | {
32 | ///
33 | /// Combines a bunch of filters together.
34 | ///
35 | public class CompositeFilter : IFilter
36 | {
37 | private readonly IList _filters;
38 |
39 | public CompositeFilter(IList filters)
40 | {
41 | _filters = filters;
42 | }
43 |
44 | public IEnumerable Filter(IEnumerable tSqlObjects)
45 | {
46 | foreach (IFilter filter in _filters)
47 | {
48 | tSqlObjects = filter.Filter(tSqlObjects);
49 | }
50 |
51 | return tSqlObjects;
52 | }
53 |
54 | public void Initialize(Dictionary filterArguments)
55 | {
56 | // Do nothing
57 | }
58 | }
59 | }
--------------------------------------------------------------------------------
/Samples/Contributors/AlterTableAlterColumnOnlineModifier.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | //
4 | // The MIT License (MIT)
5 | //
6 | // Copyright (c) 2015 Microsoft
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 | //------------------------------------------------------------------------------
27 |
28 | using Microsoft.SqlServer.Dac.Deployment;
29 | using Microsoft.SqlServer.Dac.Model;
30 | using Microsoft.SqlServer.TransactSql.ScriptDom;
31 | using System;
32 | using System.Collections;
33 | using System.Collections.Generic;
34 |
35 | namespace Public.Dac.Samples.Contributors
36 | {
37 | ///
38 | /// This deployment contributor allows ALTER TABLE...ALTER COLUMN operations to be done online (this is a new feature supported in SQL 2016 and in Azure SQL DB)
39 | ///
40 | ///
41 | /// This sample was created based on an actual customer scenario where deployments happen when the workload is still active. In those cases, any ALTER TABLE...ALTER COLUMN
42 | /// operations took the table 'offline' and caused blocking. Using this deployment contributor leverages the new online alter column functionality and minimizes such blocking.
43 | ///
44 | [ExportDeploymentPlanModifier(ContributorId, "1.0.0.0")]
45 | public class AlterTableAlterColumnOnlineModifier : DeploymentPlanModifier
46 | {
47 | public const string ContributorId = "Public.Dac.Samples.Contributors.AlterTableAlterColumnOnlineModifier";
48 |
49 | protected override void OnExecute(DeploymentPlanContributorContext context)
50 | {
51 | this.FindAndMakeAlterColumnsOnline(context);
52 | }
53 |
54 | private void FindAndMakeAlterColumnsOnline(DeploymentPlanContributorContext context)
55 | {
56 | DeploymentStep nextStep = context.PlanHandle.Head;
57 |
58 | // Loop through all steps in the deployment plan
59 | bool foundMainSection = false;
60 | while (nextStep != null)
61 | {
62 | DeploymentStep currentStep = nextStep;
63 | nextStep = currentStep.Next;
64 |
65 | // We only want to analyze the main part of the deployment script - we'll skip
66 | // any steps until we pass the end of the predeployment section, and stop once
67 | // we hit the start of the postdeployment section
68 | if (currentStep is EndPreDeploymentScriptStep)
69 | {
70 | foundMainSection = true;
71 | continue;
72 | }
73 |
74 | if (!foundMainSection)
75 | {
76 | // Haven't gotten past predeployment yet
77 | continue;
78 | }
79 |
80 | if (currentStep is BeginPostDeploymentScriptStep)
81 | {
82 | break;
83 | }
84 |
85 | // We need to care about AlterElementSteps.
86 | DeploymentScriptDomStep domStep = currentStep as DeploymentScriptDomStep;
87 | TSqlObject elementObject = null;
88 |
89 | if (domStep is AlterElementStep)
90 | {
91 | elementObject = ((AlterElementStep)domStep).SourceElement;
92 | }
93 |
94 | if (elementObject != null)
95 | {
96 | TSqlFragment fragment = domStep.Script;
97 |
98 | // call the visitor, which in turn will auto-name these constraints
99 | var visitor = new AlterTableAlterColumnVisitor();
100 | fragment.Accept(visitor);
101 | }
102 | }
103 | }
104 |
105 | private class AlterTableAlterColumnVisitor : TSqlConcreteFragmentVisitor
106 | {
107 | ///
108 | /// This visitor looks for ALTER TABLE...ALTER COLUMN statements and overrides by adding ONLINE = ON attribute
109 | ///
110 | public override void ExplicitVisit(AlterTableAlterColumnStatement node)
111 | {
112 | bool isAlreadyOnline = false;
113 |
114 | // check if the statement already has ONLINE = ON
115 | foreach(var option in node.Options)
116 | {
117 | if (option is OnlineIndexOption)
118 | {
119 | isAlreadyOnline = true;
120 | }
121 | }
122 |
123 | if (!isAlreadyOnline)
124 | {
125 | node.Options.Add(new OnlineIndexOption()
126 | {
127 | OptionKind = IndexOptionKind.Online,
128 | OptionState = OptionState.On
129 | });
130 | }
131 | }
132 | }
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/Samples/Contributors/DefaultConstraintNameModifier.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | //
4 | // The MIT License (MIT)
5 | //
6 | // Copyright (c) 2015 Microsoft
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 | //------------------------------------------------------------------------------
27 |
28 | using Microsoft.SqlServer.Dac.Deployment;
29 | using Microsoft.SqlServer.Dac.Model;
30 | using Microsoft.SqlServer.TransactSql.ScriptDom;
31 | using System;
32 | using System.Collections;
33 | using System.Collections.Generic;
34 |
35 | namespace Public.Dac.Samples.Contributors
36 | {
37 | ///
38 | /// This deployment contributor explicitly names unnamed default constraints with a auto-generated GUID name.
39 | ///
40 | ///
41 | /// This sample was created based on an actual customer scenario where there was a mixture of 'named' and un-named default constraints
42 | /// The reason 'named' is in quotes is that in that scenario the name was actually a previously auto-generated default constraint name
43 | /// (for example the 'named' constraint was named DF__Contoso_A__IsOld__3BEC4C22).
44 | ///
45 | /// Due to a non-deterministic order in which these constraints get deployed by DacFX, if the unnamed constraint was deployed first, and then
46 | /// an named constraint deployed afterwards, in some rare cases the deployment due to a name clash.
47 | ///
48 | /// This sample aims to fix the issue by explicitly naming all unnamed default constraints.
49 | ///
50 | [ExportDeploymentPlanModifier(ContributorId, "1.0.0.0")]
51 | public class DefaultConstraintNameModifier : DeploymentPlanModifier
52 | {
53 | public const string ContributorId = "Public.Dac.Samples.Contributors.DefaultConstraintNameModifier";
54 |
55 | protected override void OnExecute(DeploymentPlanContributorContext context)
56 | {
57 | this.FindAndRenameUnnamedDefaultConstraints(context);
58 | }
59 |
60 | private void FindAndRenameUnnamedDefaultConstraints(DeploymentPlanContributorContext context)
61 | {
62 | DeploymentStep nextStep = context.PlanHandle.Head;
63 |
64 | // Loop through all steps in the deployment plan
65 | bool foundMainSection = false;
66 | while (nextStep != null)
67 | {
68 | DeploymentStep currentStep = nextStep;
69 | nextStep = currentStep.Next;
70 |
71 | // We only want to analyze the main part of the deployment script - we'll skip
72 | // any steps until we pass the end of the predeployment section, and stop once
73 | // we hit the start of the postdeployment section
74 | if (currentStep is EndPreDeploymentScriptStep)
75 | {
76 | foundMainSection = true;
77 | continue;
78 | }
79 |
80 | if (!foundMainSection)
81 | {
82 | // Haven't gotten past predeployment yet
83 | continue;
84 | }
85 |
86 | if (currentStep is BeginPostDeploymentScriptStep)
87 | {
88 | break;
89 | }
90 |
91 | // We need to care about CreateElementSteps and AlterElementSteps for default constraints.
92 | DeploymentScriptDomStep domStep = currentStep as DeploymentScriptDomStep;
93 | TSqlObject elementObject = null;
94 |
95 | // most of the default constraints in the deployment plan seem to be deployed as Alter Table statements, but
96 | // just in case the default constraint was deployed as part of a Create Table (don't see how it is possible, but just being safe)
97 | if (domStep is CreateElementStep)
98 | {
99 | elementObject = ((CreateElementStep)domStep).SourceElement;
100 |
101 | }
102 | else if (domStep is AlterElementStep)
103 | {
104 | elementObject = ((AlterElementStep)domStep).SourceElement;
105 | }
106 |
107 | if (elementObject != null)
108 | {
109 | TSqlFragment fragment = domStep.Script;
110 |
111 | // call the visitor, which in turn will auto-name these constraints
112 | var visitor = new DefaultConstraintDefinitionVisitor();
113 | fragment.Accept(visitor);
114 | }
115 | }
116 | }
117 |
118 | private class DefaultConstraintDefinitionVisitor : TSqlConcreteFragmentVisitor
119 | {
120 | ///
121 | /// This visitor looks for default constraints without any identifier (name) and for those explicitly names them.
122 | /// In the cases where the constraint is unnamed, the ConstraintIdentifier field is null.
123 | ///
124 | public override void ExplicitVisit(DefaultConstraintDefinition node)
125 | {
126 | if (node.ConstraintIdentifier == null)
127 | {
128 | node.ConstraintIdentifier = new Identifier()
129 | {
130 | Value = string.Format("DF_autonamed_{0}", Guid.NewGuid().ToString("N"))
131 | };
132 | }
133 | }
134 | }
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/Samples/Contributors/DeploymentStoppingContributor.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | //
4 | // The MIT License (MIT)
5 | //
6 | // Copyright (c) 2015 Microsoft
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 | //------------------------------------------------------------------------------
27 | using Microsoft.SqlServer.Dac.Deployment;
28 | using Microsoft.SqlServer.Dac.Extensibility;
29 |
30 | namespace Public.Dac.Samples.Contributors
31 | {
32 | ///
33 | /// This is a sample contributor that blocks deployment. Clearly this isn't something that would be
34 | /// used in a real environment, but it shows how you go about blocking deployment from happening.
35 | /// A realistic use of this it to check for certain preconditions and block deployment if these are
36 | /// not met.
37 | ///
38 | [ExportDeploymentPlanModifier(ContributorId, "1.0.0.0")]
39 | public class DeploymentStoppingContributor : DeploymentPlanModifier
40 | {
41 | public const string ContributorId = "Public.Dac.Samples.Contributors.DeploymentStoppingContributor";
42 | public const string ErrorViaPublishMessage = "Data Motion Detected!";
43 | public const string ErrorViaThrownException = "Data Motion Detected!";
44 |
45 | ///
46 | /// Iterates over the deployment plan to find the definition for
47 | ///
48 | ///
49 | protected override void OnExecute(DeploymentPlanContributorContext context)
50 | {
51 | var planStep = context.PlanHandle.Head;
52 | while (planStep != null)
53 | {
54 | if (planStep is SqlTableMigrationStep)
55 | {
56 | // Publishing Severity.Error message blocks deployment
57 | base.PublishMessage(new ExtensibilityError(ErrorViaPublishMessage, Severity.Error));
58 |
59 | // Alternatively throwing an exception will also block deployment
60 | throw new DeploymentFailedException(ErrorViaThrownException);
61 | }
62 | planStep = planStep.Next;
63 | }
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/Samples/DisposableList.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | //
4 | // The MIT License (MIT)
5 | //
6 | // Copyright (c) 2015 Microsoft
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 | //------------------------------------------------------------------------------
27 | using System;
28 | using System.Collections.Generic;
29 |
30 | namespace Public.Dac.Samples
31 | {
32 | ///
33 | /// Utility class for tracking and disposing of objects that implement IDisposable.
34 | ///
35 | public sealed class DisposableList : List, IDisposable
36 | {
37 | ///
38 | /// Disposes of all elements of list.
39 | ///
40 | public void Dispose()
41 | {
42 | Dispose(true);
43 | }
44 |
45 | ///
46 | /// Internal implementation of Dispose logic.
47 | ///
48 | private void Dispose(bool isDisposing)
49 | {
50 | foreach (IDisposable disposable in this)
51 | {
52 | disposable.Dispose();
53 | }
54 | }
55 |
56 | ///
57 | /// Add an item to the list.
58 | ///
59 | public T Add(T item) where T : IDisposable
60 | {
61 | base.Add(item);
62 |
63 | return item;
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/Samples/Filter.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | //
4 | // The MIT License (MIT)
5 | //
6 | // Copyright (c) 2015 Microsoft
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 | //------------------------------------------------------------------------------
27 | using Microsoft.SqlServer.Dac.Model;
28 | using System.Collections.Generic;
29 |
30 | namespace Public.Dac.Samples
31 | {
32 | ///
33 | /// A Filter should take in a set of TSqlObjects, filter them based on some criteria,
34 | /// and return a (smaller) set of objects.
35 | ///
36 | public interface IFilter
37 | {
38 | ///
39 | /// Filter a stream of TSqlObjects based on some criteria
40 | ///
41 | /// the objects to filter
42 | /// some filtered set of objects
43 | IEnumerable Filter(IEnumerable tSqlObjects);
44 |
45 | ///
46 | /// Provides a chance to initialize the filter based on some set of key-value pairs.
47 | /// Note that this kind of method would be better in an abstract parent class than in an interface
48 | /// since only some filters would need this. This would be something to improve on if using this in a real application
49 | ///
50 | /// set of key value pairs that can be used to initialize the filter
51 | void Initialize(Dictionary filterArguments);
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/Samples/PlanFilterer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | //
4 | // The MIT License (MIT)
5 | //
6 | // Copyright (c) 2015 Microsoft
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 | //------------------------------------------------------------------------------
27 | using Microsoft.SqlServer.Dac.Deployment;
28 | using Microsoft.SqlServer.Dac.Model;
29 | using System;
30 | using System.Collections.Generic;
31 | using System.Linq;
32 | using System.Text;
33 |
34 | namespace Public.Dac.Samples
35 | {
36 | ///
37 | /// A Deployment plan modifier that filters "Create Element" steps from a deployment plan.
38 | /// This stops elements from being created. This is a simple example. A more advanced
39 | /// version of this would probably check any SqlRenameSteps in the plan, but for this
40 | /// sample we're assuming that this isn't something the developer would have done.
41 | ///
42 | [ExportDeploymentPlanModifier(PlanFilterer.PlanFiltererContributorId, "1.0.0.0")]
43 | public class PlanFilterer : DeploymentPlanModifier
44 | {
45 | public const string PlanFiltererContributorId = "Public.Dac.Samples.PlanFilterer";
46 | public const string FilterNameArg = "FilterName";
47 |
48 | private static Dictionary> _filterMap = new Dictionary>()
49 | {
50 | {"SchemaBasedFilter", new Lazy(() => new SchemaBasedFilter())}
51 | };
52 |
53 | private IFilter _filter;
54 |
55 | protected override void OnExecute(DeploymentPlanContributorContext context)
56 | {
57 | InitializeFilter(context.Arguments);
58 | DeploymentStep next = context.PlanHandle.Head;
59 | while (next != null)
60 | {
61 | DeploymentStep current = next;
62 | next = current.Next;
63 |
64 | CreateElementStep createStep = current as CreateElementStep;
65 | if (createStep != null && ShouldFilter(createStep))
66 | {
67 | base.Remove(context.PlanHandle, createStep);
68 | }
69 | }
70 | }
71 |
72 | ///
73 | /// We should filter the step if the source element for the step
74 | /// doesn't pass the filter
75 | ///
76 | private bool ShouldFilter(CreateElementStep createStep)
77 | {
78 | TSqlObject createdObject = createStep.SourceElement;
79 | return !_filter.Filter(new[] {createdObject}).Any();
80 | }
81 |
82 | private void InitializeFilter(Dictionary arguments)
83 | {
84 | string filterName;
85 | if (arguments.TryGetValue(FilterNameArg, out filterName)
86 | && _filterMap.ContainsKey(filterName))
87 | {
88 | // Note: could use MEF or some other lookup technique to find a specific filter. If you
89 | // just have a few known filters, a map like this might be a good idea
90 | _filter = _filterMap[filterName].Value;
91 | _filter.Initialize(arguments);
92 | }
93 | }
94 |
95 | ///
96 | /// Builds the arguments string to be passed to the DacServices API when running the contributor
97 | ///
98 | public static string BuildPlanFiltererArgumentString(string filterName,
99 | Dictionary filterArguments)
100 | {
101 | filterArguments[FilterNameArg] = filterName;
102 | return Utils.BuildContributorArguments(filterArguments);
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/Samples/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | //
4 | // The MIT License (MIT)
5 | //
6 | // Copyright (c) 2015 Microsoft
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 | //------------------------------------------------------------------------------
27 | using System.Reflection;
28 | using System.Runtime.CompilerServices;
29 | using System.Runtime.InteropServices;
30 |
31 | // General Information about an assembly is controlled through the following
32 | // set of attributes. Change these attribute values to modify the information
33 | // associated with an assembly.
34 | [assembly: AssemblyTitle("Samples")]
35 | [assembly: AssemblyDescription("")]
36 | [assembly: AssemblyConfiguration("")]
37 | [assembly: AssemblyCompany("")]
38 | [assembly: AssemblyProduct("Samples")]
39 | [assembly: AssemblyCopyright("Copyright © 2013")]
40 | [assembly: AssemblyTrademark("")]
41 | [assembly: AssemblyCulture("")]
42 |
43 | // Setting ComVisible to false makes the types in this assembly not visible
44 | // to COM components. If you need to access a type in this assembly from
45 | // COM, set the ComVisible attribute to true on that type.
46 | [assembly: ComVisible(false)]
47 |
48 | // The following GUID is for the ID of the typelib if this project is exposed to COM
49 | [assembly: Guid("32be1e6f-b4e1-4a2d-9685-ee37872fd011")]
50 |
51 | // Version information for an assembly consists of the following four values:
52 | //
53 | // Major Version
54 | // Minor Version
55 | // Build Number
56 | // Revision
57 | //
58 | // You can specify all the values or you can default the Build and Revision Numbers
59 | // by using the '*' as shown below:
60 | // [assembly: AssemblyVersion("1.0.*")]
61 | [assembly: AssemblyVersion("1.0.0.0")]
62 | [assembly: AssemblyFileVersion("1.0.0.0")]
63 |
--------------------------------------------------------------------------------
/Samples/Samples.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {C1C2B521-22B6-4124-AAEC-A5E1FCAB0DFA}
8 | Library
9 | Properties
10 | Public.Dac.Samples
11 | Public.Dac.Samples
12 | v4.6
13 | 512
14 |
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 |
33 |
34 |
35 | ..\packages\Microsoft.SqlServer.DacFx.x64.150.4826.1\lib\net46\Microsoft.Data.Tools.Schema.Sql.dll
36 |
37 |
38 | ..\packages\Microsoft.SqlServer.DacFx.x64.150.4826.1\lib\net46\Microsoft.Data.Tools.Utilities.dll
39 |
40 |
41 | ..\packages\Microsoft.SqlServer.DacFx.x64.150.4826.1\lib\net46\Microsoft.SqlServer.Dac.dll
42 |
43 |
44 | ..\packages\Microsoft.SqlServer.DacFx.x64.150.4826.1\lib\net46\Microsoft.SqlServer.Dac.Extensions.dll
45 |
46 |
47 | ..\packages\Microsoft.SqlServer.DacFx.x64.150.4826.1\lib\net46\Microsoft.SqlServer.TransactSql.ScriptDom.dll
48 |
49 |
50 | ..\packages\Microsoft.SqlServer.DacFx.x64.150.4826.1\lib\net46\Microsoft.SqlServer.Types.dll
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
89 |
--------------------------------------------------------------------------------
/Samples/SchemaBasedFilter.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | //
4 | // The MIT License (MIT)
5 | //
6 | // Copyright (c) 2015 Microsoft
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 | //------------------------------------------------------------------------------
27 | using Microsoft.SqlServer.Dac.Model;
28 | using System;
29 | using System.Collections.Generic;
30 | using System.Linq;
31 |
32 | namespace Public.Dac.Samples
33 | {
34 | ///
35 | /// Simple filter that compares to schema name. Note that this does not use the model
36 | /// collation - for a more robust filter an would be
37 | /// used that checked the collation.
38 | ///
39 | public class SchemaBasedFilter : IFilter
40 | {
41 | public const string SchemaNameArg = "Schema";
42 |
43 | public enum FilterType
44 | {
45 | ///
46 | /// Default
47 | ///
48 | Exclude,
49 | Include
50 | }
51 |
52 | private HashSet _schemaNames;
53 |
54 | ///
55 | /// Creates a filter for the specified , with the
56 | /// default filtering behavior to remove objects with the given schema names.
57 | ///
58 | ///
59 | public SchemaBasedFilter(params string[] schemaNames)
60 | : this((IList) schemaNames)
61 | {
62 | }
63 |
64 | ///
65 | /// Creates a filter for the specified , with the
66 | /// default filtering behavior to remove objects with the given schema names.
67 | ///
68 | ///
69 | public SchemaBasedFilter(IList schemaNames)
70 | {
71 | _schemaNames = new HashSet(schemaNames);
72 | Filtering = FilterType.Exclude;
73 | }
74 |
75 | ///
76 | /// This would be called by a deployment contributor to initialize the filter. The
77 | /// assumption is that in the code that runs the deployment, a number of arguments
78 | /// "Schema1=dev;Schema2=test" would be passed into the contributor arguments
79 | ///
80 | public void Initialize(Dictionary filterArguments)
81 | {
82 | var schemaNames = filterArguments
83 | .Where(pair => pair.Key.StartsWith(SchemaNameArg))
84 | .Select(pair => pair.Value);
85 |
86 | _schemaNames = new HashSet(schemaNames);
87 |
88 | // Currently there is no "FilterType" argument that would allow us to
89 | // specify the filter's behavior. For now, will always by in "Exclude" mode
90 | }
91 |
92 | ///
93 | /// What type of filtering to use. Defaults to
94 | ///
95 | public FilterType Filtering
96 | {
97 | get;
98 | set;
99 | }
100 |
101 | public IEnumerable Filter(IEnumerable tSqlObjects)
102 | {
103 | return tSqlObjects.Where(o => ShouldInclude(o));
104 | }
105 |
106 |
107 | private bool ShouldInclude(TSqlObject tsqlObject)
108 | {
109 | // almost all top-level TSqlObjects are expected to have a name.
110 | // The ObjectIdentifier
111 | bool found = false;
112 | ObjectIdentifier id = tsqlObject.Name;
113 | if (id.HasName && id.Parts.Count >= 1)
114 | {
115 | // Assuming schema name is always the first part.
116 | string schemaName = id.Parts[0];
117 | found = _schemaNames.Contains(schemaName, StringComparer.OrdinalIgnoreCase);
118 | }
119 |
120 | if (Filtering == FilterType.Exclude)
121 | {
122 | // exclude any objects whose schema was in the filter list
123 | return !found;
124 | }
125 | return found;
126 | }
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/Samples/Utils.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | //
4 | // The MIT License (MIT)
5 | //
6 | // Copyright (c) 2015 Microsoft
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 | //------------------------------------------------------------------------------
27 | using Microsoft.SqlServer.Dac;
28 | using System.Collections.Generic;
29 | using System.Text;
30 |
31 | namespace Public.Dac.Samples
32 | {
33 | ///
34 | /// Useful utility methods that the samples can use
35 | ///
36 | public static class Utils
37 | {
38 |
39 | ///
40 | /// Builds the arguments string to be used when running contributors. This should be
41 | /// set as the when
42 | /// running deployment via the API.
43 | ///
44 | public static string BuildContributorArguments(Dictionary arguments)
45 | {
46 | StringBuilder args = new StringBuilder();
47 |
48 | foreach (var entry in arguments)
49 | {
50 | AddArgument(args, entry.Key, entry.Value);
51 | }
52 | return args.ToString();
53 | }
54 |
55 | ///
56 | /// Adds an argument into the string. Args are name-value pairs separated by the "=" sign, with
57 | /// each argument in the list semicolon delimited. Hence and arg string might look like
58 | /// "FilterName=SchemaBasedFilter;Schema1=dev;Schema2=test"
59 | ///
60 | private static void AddArgument(StringBuilder args, string key, string value)
61 | {
62 | if (args.Length > 0)
63 | {
64 | args.Append(";");
65 | }
66 | args.Append(key).Append("=").Append(value);
67 | }
68 |
69 | ///
70 | /// Builds the string describing the contributors to be run - this should be
71 | /// set as the when
72 | /// running deployment via the API.
73 | ///
74 | /// Names of the contributors to be run
75 | /// semi-colon delimited string describing the contributors to be run
76 | public static string BuildContributorsList(IList contributors)
77 | {
78 | StringBuilder args = new StringBuilder();
79 |
80 | foreach (var contributor in contributors)
81 | {
82 | AddContributor(args, contributor);
83 | }
84 | return args.ToString();
85 | }
86 |
87 | private static void AddContributor(StringBuilder args, string contributor)
88 | {
89 | if (args.Length > 0)
90 | {
91 | args.Append(";");
92 | }
93 | args.Append(contributor);
94 | }
95 |
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/Samples/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Scripts/RemoveMasterKey.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Given a new [file].bacpac, creates a new [file]-patched.bacpac with master key information removed from the model.xml and origin.xml.
4 | .DESCRIPTION
5 | When exporting a .bacpac from Azure SQLDB with auditing enabled, the .bacpac will contain a master key without a password in the model.xml. A
6 | master key without a password is an Azure SQLDB only feature, so it's presence prevents being able to import the .bacpac into an on-premise
7 | SQL Server database. This script works around this limitation by extracting the model.xml and origin.xml from the .bacpac, removing the references
8 | to the master key, and creating a new .bacpac with the updated model.xml and origin.xml. The resulting .bacpac can then be imported to an on-premise
9 | database.
10 | .EXAMPLE
11 | C:\PS> .\RemoveMasterKey.ps1 -bacpacPath "C:\BacPacs\Test.bacpac" # Generates a Test-patched.bacpac file
12 | .PARAMETER bacpacPath
13 | Specifies the path the .bacpac to patch.
14 | #>
15 | param(
16 | [Parameter(Mandatory=$true, HelpMessage="Specifies the path the .bacpac. This file will not be modified.")]
17 | [string]$bacpacPath
18 | )
19 |
20 |
21 | if ($PSVersionTable.PSVersion.Major -lt 4) {
22 | Write-Host "Unsupported powershell version. This script requires powershell version 4.0 or later"
23 | return
24 | }
25 |
26 |
27 | Add-Type -Assembly System.IO.Compression.FileSystem
28 |
29 |
30 | $targetBacpacPath = [System.IO.Path]::Combine(
31 | [System.IO.Path]::GetDirectoryName($bacpacPath),
32 | [System.IO.Path]::GetFileNameWithoutExtension($bacpacPath) + "-patched" + [System.IO.Path]::GetExtension($bacpacPath))
33 | $originXmlFile = [System.IO.Path]::Combine([System.IO.Path]::GetDirectoryName($targetBacpacPath), "Origin.xml")
34 | $modelXmlFile = [System.IO.Path]::Combine([System.IO.Path]::GetDirectoryName($targetBacpacPath), "model.xml")
35 |
36 |
37 | if ([System.IO.File]::Exists($targetBacpacPath)) {
38 | [System.IO.File]::Delete($targetBacpacPath)
39 | }
40 |
41 |
42 | #
43 | # Extract the model.xml and Origin.xml from the .bacpac
44 | #
45 | $zip = [System.IO.Compression.ZipFile]::OpenRead($bacpacPath)
46 | foreach ($entry in $zip.Entries) {
47 | if ([string]::Compare($entry.Name, "model.xml", $True) -eq 0) {
48 | [System.IO.Compression.ZipFileExtensions]::ExtractToFile($entry, $modelXmlFile, $true)
49 | break
50 | }
51 | }
52 | foreach ($entry in $zip.Entries) {
53 | if ([string]::Compare($entry.Name, "Origin.xml", $True) -eq 0) {
54 | [System.IO.Compression.ZipFileExtensions]::ExtractToFile($entry, $originXmlFile, $true)
55 | break
56 | }
57 | }
58 | $zip.Dispose()
59 |
60 |
61 | if(![System.IO.File]::Exists($modelXmlFile)) {
62 | Write-Host "Could not extract the model.xml from file " + $bacpacPath
63 | return
64 | }
65 | if(![System.IO.File]::Exists($originXmlFile)) {
66 | Write-Host "Could not extract the Origin.xml from file " + $bacpacPath
67 | return
68 | }
69 |
70 |
71 | #
72 | # Modify the model.xml
73 | #
74 | [xml]$modelXml = Get-Content $modelXmlFile
75 | $ns = New-Object System.Xml.XmlNamespaceManager($modelXml.NameTable)
76 | $ns.AddNamespace("x", $modelXml.DocumentElement.NamespaceURI)
77 |
78 |
79 | $masterKeyNodes = $modelXml.SelectNodes("//x:DataSchemaModel/x:Model/x:Element[@Type='SqlMasterKey']", $ns)
80 | foreach ($masterKeyNode in $masterKeyNodes) {
81 | $masterKeyNode.ParentNode.RemoveChild($masterKeyNode)
82 | }
83 |
84 |
85 | $sqlDatabaseCredentialNodes = $modelXml.SelectNodes("//x:DataSchemaModel/x:Model/x:Element[@Type='SqlDatabaseCredential']", $ns)
86 | foreach ($sqlDatabaseCredentialNode in $sqlDatabaseCredentialNodes) {
87 | if ($sqlDatabaseCredentialNode.Property.Name -eq "Identity" -and $sqlDatabaseCredentialNode.Property.Value -eq "SHARED ACCESS SIGNATURE")
88 | {
89 | $sqlDatabaseCredentialNode.ParentNode.RemoveChild($sqlDatabaseCredentialNode)
90 | }
91 | }
92 |
93 |
94 | $modelXml.Save($modelXmlFile)
95 |
96 |
97 | #
98 | # Modify the Origin.xml
99 | #
100 | [xml]$originXml = Get-Content $originXmlFile
101 | $ns = New-Object System.Xml.XmlNamespaceManager($originXml.NameTable)
102 | $ns.AddNamespace("x", $originXml.DocumentElement.NamespaceURI)
103 |
104 |
105 | $databaseCredentialNode = $originXml.SelectSingleNode("//x:DacOrigin/x:Server/x:ObjectCounts/x:DatabaseCredential", $ns)
106 | if ($databaseCredentialNode) {
107 | if ($databaseCredentialNode.InnerText -eq "1") {
108 | $databaseCredentialNode.ParentNode.RemoveChild($databaseCredentialNode)
109 | } else {
110 | $databaseCredentialNode.InnerText = $databaseCredentialNode.Value - 1
111 | }
112 | }
113 |
114 |
115 | $masterKeyNode = $originXml.SelectSingleNode("//x:DacOrigin/x:Server/x:ObjectCounts/x:MasterKey", $ns)
116 | if ($masterKeyNode) {
117 | $masterKeyNode.ParentNode.RemoveChild($masterKeyNode)
118 | }
119 |
120 |
121 | $modelXmlHash = (Get-FileHash $modelXmlFile -Algorithm SHA256).Hash
122 | $checksumNode = $originXml.SelectSingleNode("//x:DacOrigin/x:Checksums/x:Checksum", $ns)
123 | if ($checksumNode) {
124 | $checksumNode.InnerText = $modelXmlHash
125 | }
126 |
127 |
128 | $originXml.Save($originXmlFile)
129 |
130 |
131 | #
132 | # Create the new .bacpac using the patched model.xml and Origin.xml
133 | #
134 | $zipSource = [System.IO.Compression.ZipFile]::OpenRead($bacpacPath)
135 | $zipTarget = [System.IO.Compression.ZipFile]::Open($targetBacpacPath, "Create")
136 | foreach ($entry in $zipSource.Entries) {
137 | if ([string]::Compare($entry.Name, "Origin.xml", $True) -eq 0) {
138 | [System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($zipTarget, $originXmlFile, $entry.FullName)
139 | } elseif ([string]::Compare($entry.Name, "model.xml", $True) -eq 0) {
140 | [System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($zipTarget, $modelXmlFile, $entry.FullName)
141 | } else {
142 | $targetEntry = $zipTarget.CreateEntry($entry.FullName)
143 | $sourceStream = $null
144 | $targetStream = $null
145 | try {
146 | $sourceStream = [System.IO.Stream]$entry.Open()
147 | $targetStream = [System.IO.Stream]$targetEntry.Open()
148 | $sourceStream.CopyTo($targetStream)
149 | }
150 | finally {
151 | if ($targetStream -ne $null) {
152 | $targetStream.Dispose()
153 | }
154 | if ($sourceStream -ne $null) {
155 | $sourceStream.Dispose()
156 | }
157 | }
158 | }
159 | }
160 | $zipSource.Dispose()
161 | $zipTarget.Dispose()
162 |
163 |
164 | [System.IO.File]::Delete($modelXmlFile)
165 | [System.IO.File]::Delete($originXmlFile)
166 |
167 |
168 | Write-Host "Completed update to the model.xml and Origin.xml in file"([System.IO.Path]::GetFullPath($targetBacpacPath))
--------------------------------------------------------------------------------
/TestUtils/CommonConstants.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | //
4 | // The MIT License (MIT)
5 | //
6 | // Copyright (c) 2015 Microsoft
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 | //------------------------------------------------------------------------------
27 |
28 | namespace Public.Dac.Samples.TestUtilities
29 | {
30 | internal class CommonConstants
31 | {
32 | public const string MasterDatabaseName = "master";
33 |
34 | public const int DefaultSqlQueryTimeoutInSeconds = 60;
35 |
36 | public const int DefaultCommandTimeout = 30;
37 | }
38 | }
--------------------------------------------------------------------------------
/TestUtils/ExceptionText.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | //
4 | // The MIT License (MIT)
5 | //
6 | // Copyright (c) 2015 Microsoft
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 | //------------------------------------------------------------------------------
27 |
28 | using System;
29 | using System.Text;
30 |
31 | namespace Public.Dac.Samples.TestUtilities
32 | {
33 |
34 | public static class ExceptionText
35 | {
36 | public static string GetText(Exception ex, bool stackTrace = false)
37 | {
38 | StringBuilder sb = new StringBuilder();
39 | int depth = 0;
40 | while (ex != null)
41 | {
42 | if (depth > 0)
43 | {
44 | sb.Append("Inner Exception: ");
45 | }
46 | sb.AppendLine(ex.Message);
47 | if (stackTrace)
48 | {
49 | sb.AppendLine(ex.StackTrace);
50 | }
51 | ex = ex.InnerException;
52 | ++depth;
53 | }
54 | return sb.ToString();
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/TestUtils/InstanceInfo.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | //
4 | // The MIT License (MIT)
5 | //
6 | // Copyright (c) 2015 Microsoft
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 | //------------------------------------------------------------------------------
27 |
28 | using System;
29 | using System.Data.SqlClient;
30 |
31 | namespace Public.Dac.Samples.TestUtilities
32 | {
33 |
34 | public class InstanceInfo
35 | {
36 |
37 | public InstanceInfo(string dataSource)
38 | {
39 | DataSource = dataSource;
40 | }
41 |
42 | // Persisted data properties
43 | public string DataSource { get; set; }
44 |
45 | public string RemoteSharePath { get; set; }
46 |
47 | public int ConnectTimeout { get; set; }
48 |
49 | public string ConnectTimeoutAsString
50 | {
51 | get { return ConnectTimeout.ToString(); }
52 | set
53 | {
54 | int temp;
55 | if (int.TryParse(value, out temp))
56 | {
57 | this.ConnectTimeout = temp;
58 | }
59 | else
60 | {
61 | this.ConnectTimeout = 15;
62 | }
63 | }
64 | }
65 |
66 |
67 | public string MachineName
68 | {
69 | get
70 | {
71 | string serverName = DataSource;
72 | int index = DataSource.IndexOf('\\');
73 | if (index > 0)
74 | {
75 | serverName = DataSource.Substring(0, index);
76 | }
77 | if (StringComparer.OrdinalIgnoreCase.Compare("(local)", serverName) == 0
78 | || StringComparer.OrdinalIgnoreCase.Compare(".", serverName) == 0)
79 | {
80 | serverName = Environment.MachineName;
81 | }
82 | return serverName;
83 | }
84 | }
85 | public string InstanceName
86 | {
87 | get
88 | {
89 | string name = null;
90 | int index = DataSource.IndexOf('\\');
91 | if (index > 0)
92 | {
93 | name = DataSource.Substring(index + 1);
94 | }
95 | return name;
96 | }
97 | }
98 |
99 | public string UserId { get; set; }
100 |
101 | public string Password { get; set; }
102 |
103 | ///
104 | /// Connection string to this instance with the master database as the default.
105 | /// Integrated security is used
106 | ///
107 | ///
108 | public string BuildConnectionString()
109 | {
110 | return CreateBuilder().ConnectionString;
111 | }
112 |
113 | public SqlConnectionStringBuilder CreateBuilder()
114 | {
115 | return CreateBuilder(CommonConstants.MasterDatabaseName);
116 | }
117 |
118 | public string BuildConnectionString(string dbName)
119 | {
120 | return CreateBuilder(dbName).ConnectionString;
121 | }
122 |
123 | public SqlConnectionStringBuilder CreateBuilder(string dbName)
124 | {
125 | return CreateBuilder(UserId, Password, dbName);
126 | }
127 |
128 | ///
129 | /// Build a connection string for this instance using the specified
130 | /// username/password for security and specifying the dbName as the
131 | /// initial catalog
132 | ///
133 | public string BuildConnectionString(string userId, string password, string dbName)
134 | {
135 | SqlConnectionStringBuilder scsb = CreateBuilder(userId, password, dbName);
136 | return scsb.ConnectionString;
137 | }
138 | public SqlConnectionStringBuilder CreateBuilder(string userId, string password, string dbName)
139 | {
140 | SqlConnectionStringBuilder scsb = new SqlConnectionStringBuilder();
141 | scsb.DataSource = DataSource;
142 | scsb.InitialCatalog = dbName;
143 | scsb.Pooling = false;
144 | scsb.MultipleActiveResultSets = false;
145 | if (ConnectTimeout != 15)
146 | {
147 | scsb.ConnectTimeout = this.ConnectTimeout;
148 | }
149 |
150 | if (string.IsNullOrEmpty(userId) || string.IsNullOrEmpty(password))
151 | {
152 | scsb.IntegratedSecurity = true;
153 | }
154 | else
155 | {
156 | scsb.IntegratedSecurity = false;
157 | scsb.UserID = userId;
158 | scsb.Password = password;
159 | }
160 |
161 | return scsb;
162 | }
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/TestUtils/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | //
4 | // The MIT License (MIT)
5 | //
6 | // Copyright (c) 2015 Microsoft
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 | //------------------------------------------------------------------------------
27 |
28 | using System.Reflection;
29 | using System.Runtime.CompilerServices;
30 | using System.Runtime.InteropServices;
31 |
32 | // General Information about an assembly is controlled through the following
33 | // set of attributes. Change these attribute values to modify the information
34 | // associated with an assembly.
35 | [assembly: AssemblyTitle("Public.Dac.Samples.TestUtilitiess")]
36 | [assembly: AssemblyDescription("")]
37 | [assembly: AssemblyConfiguration("")]
38 | [assembly: AssemblyCompany("")]
39 | [assembly: AssemblyProduct("TestUtils")]
40 | [assembly: AssemblyCopyright("Copyright © 2015")]
41 | [assembly: AssemblyTrademark("")]
42 | [assembly: AssemblyCulture("")]
43 |
44 | // Setting ComVisible to false makes the types in this assembly not visible
45 | // to COM components. If you need to access a type in this assembly from
46 | // COM, set the ComVisible attribute to true on that type.
47 | [assembly: ComVisible(false)]
48 |
49 | // The following GUID is for the ID of the typelib if this project is exposed to COM
50 | [assembly: Guid("edf01d79-66d0-496c-82d2-431831564817")]
51 |
52 | // Version information for an assembly consists of the following four values:
53 | //
54 | // Major Version
55 | // Minor Version
56 | // Build Number
57 | // Revision
58 | //
59 | // You can specify all the values or you can default the Build and Revision Numbers
60 | // by using the '*' as shown below:
61 | // [assembly: AssemblyVersion("1.0.*")]
62 | [assembly: AssemblyVersion("1.0.0.0")]
63 | [assembly: AssemblyFileVersion("1.0.0.0")]
64 |
--------------------------------------------------------------------------------
/TestUtils/TestUtils.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {EDF01D79-66D0-496C-82D2-431831564817}
8 | Library
9 | Properties
10 | Public.Dac.Samples.TestUtilities
11 | Public.Dac.Samples.TestUtilitiess
12 | v4.6
13 | 512
14 |
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 |
33 |
34 |
35 | ..\packages\Microsoft.SqlServer.DacFx.x64.150.4826.1\lib\net46\Microsoft.Data.Tools.Schema.Sql.dll
36 |
37 |
38 | ..\packages\Microsoft.SqlServer.DacFx.x64.150.4826.1\lib\net46\Microsoft.Data.Tools.Utilities.dll
39 |
40 |
41 | ..\packages\Microsoft.SqlServer.DacFx.x64.150.4826.1\lib\net46\Microsoft.SqlServer.Dac.dll
42 |
43 |
44 | ..\packages\Microsoft.SqlServer.DacFx.x64.150.4826.1\lib\net46\Microsoft.SqlServer.Dac.Extensions.dll
45 |
46 |
47 | ..\packages\Microsoft.SqlServer.DacFx.x64.150.4826.1\lib\net46\Microsoft.SqlServer.TransactSql.ScriptDom.dll
48 |
49 |
50 | ..\packages\Microsoft.SqlServer.DacFx.x64.150.4826.1\lib\net46\Microsoft.SqlServer.Types.dll
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
80 |
--------------------------------------------------------------------------------
/TestUtils/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------