├── .azure
└── pipelines
│ └── ci.yml
├── .editorconfig
├── .github
└── dependabot.yml
├── .gitignore
├── LICENSE.md
├── Madd0.AzureStorageDriver.sln
├── Madd0.AzureStorageDriver
├── AzureDriver.cs
├── Compiler
│ ├── CodeDomCompiler.cs
│ ├── ICompiler.cs
│ └── RoslynCompiler.cs
├── ConnectionDialog.xaml
├── ConnectionDialog.xaml.cs
├── DataContextTemplate.cs
├── DataContextTemplate.tt
├── Madd0.AzureStorageDriver.csproj
├── Model
│ ├── AzureEnvironment.cs
│ ├── CloudTable.cs
│ ├── GenericEntity.cs
│ ├── StorageAccountProperties.cs
│ └── TableColumn.cs
├── Properties
│ ├── Exceptions.Designer.cs
│ ├── Exceptions.resx
│ ├── Resources.Designer.cs
│ └── Resources.resx
├── SchemaBuilder.cs
├── UserQuery
│ └── ExtendedTableQuery.cs
└── header.xml
├── README.md
└── Settings.XamlStyler
/.azure/pipelines/ci.yml:
--------------------------------------------------------------------------------
1 | # .NET Desktop
2 | # Build and run tests for .NET Desktop or Windows classic desktop solutions.
3 | # Add steps that publish symbols, save build artifacts, and more:
4 | # https://docs.microsoft.com/azure/devops/pipelines/apps/windows/dot-net
5 |
6 | # Configure which branches trigger builds
7 | trigger:
8 | batch: true
9 | branches:
10 | include:
11 | - master
12 | - develop
13 | paths:
14 | exclude:
15 | - .azure/*
16 | - LICENSE.md
17 | - README.md
18 |
19 | # Run PR validation on all branches
20 | pr:
21 | autoCancel: true
22 | branches:
23 | include:
24 | - '*'
25 |
26 | pool:
27 | vmImage: 'windows-latest'
28 |
29 | variables:
30 | solution: '**/*.sln'
31 | buildPlatform: 'Any CPU'
32 | buildConfiguration: 'Release'
33 |
34 | steps:
35 | - task: NuGetToolInstaller@1
36 |
37 | - task: NuGetCommand@2
38 | inputs:
39 | restoreSolution: '$(solution)'
40 |
41 | - task: SonarCloudPrepare@1
42 | inputs:
43 | SonarCloud: 'SonarCloud New'
44 | organization: 'madd0'
45 | scannerMode: 'MSBuild'
46 | projectKey: 'madd0_AzureStorageDriver'
47 | projectName: 'madd0.AzureStorageDriver'
48 | extraProperties: |
49 | # Additional properties that will be passed to the scanner,
50 | # Put one key=value per line, example:
51 | # sonar.exclusions=**/*.bin
52 | sonar.organization=madd0
53 |
54 | - task: VSBuild@1
55 | inputs:
56 | solution: '$(solution)'
57 | msbuildArgs: '/p:BaseOutputPath=$(Build.BinariesDirectory)\\'
58 | platform: '$(buildPlatform)'
59 | configuration: '$(buildConfiguration)'
60 |
61 | - task: SonarCloudAnalyze@1
62 |
63 | - task: SonarCloudPublish@1
64 | inputs:
65 | pollingTimeoutSec: '300'
66 |
67 | - task: ArchiveFiles@2
68 | displayName: Create .NET 4.6 lpx
69 | inputs:
70 | rootFolderOrFile: '$(Build.BinariesDirectory)/$(buildConfiguration)/net46'
71 | includeRootFolder: false
72 | archiveType: 'zip'
73 | archiveFile: '$(Build.ArtifactStagingDirectory)/Madd0.AzureStorageDriver.lpx'
74 | replaceExistingArchive: true
75 |
76 | - task: ArchiveFiles@2
77 | displayName: Create .NET Core 3.1 lpx6
78 | inputs:
79 | rootFolderOrFile: '$(Build.BinariesDirectory)/$(buildConfiguration)/netcoreapp3.1'
80 | includeRootFolder: false
81 | archiveType: 'zip'
82 | archiveFile: '$(Build.ArtifactStagingDirectory)/Madd0.AzureStorageDriver.netcore31.lpx6'
83 | replaceExistingArchive: true
84 |
85 | - task: CopyFiles@2
86 | inputs:
87 | SourceFolder: '$(Build.BinariesDirectory)/$(buildConfiguration)'
88 | Contents: |
89 | *.nupkg
90 | *.snupkg
91 | TargetFolder: '$(Build.ArtifactStagingDirectory)'
92 |
93 | - task: PublishPipelineArtifact@1
94 | inputs:
95 | targetPath: '$(Build.ArtifactStagingDirectory)'
96 | publishLocation: 'pipeline'
97 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Remove the line below if you want to inherit .editorconfig settings from higher directories
2 | root = true
3 |
4 | # C# files
5 | [*.cs]
6 |
7 | #### Core EditorConfig Options ####
8 |
9 | # Indentation and spacing
10 | indent_size = 4
11 | indent_style = space
12 | tab_width = 4
13 |
14 | # New line preferences
15 | end_of_line = crlf
16 | insert_final_newline = false
17 |
18 | #### .NET Coding Conventions ####
19 |
20 | # Organize usings
21 | dotnet_separate_import_directive_groups = false
22 | dotnet_sort_system_directives_first = false
23 |
24 | # this. and Me. preferences
25 | dotnet_style_qualification_for_event = true:silent
26 | dotnet_style_qualification_for_field = false:silent
27 | dotnet_style_qualification_for_method = true:silent
28 | dotnet_style_qualification_for_property = true:silent
29 |
30 | # Language keywords vs BCL types preferences
31 | dotnet_style_predefined_type_for_locals_parameters_members = true:silent
32 | dotnet_style_predefined_type_for_member_access = true:silent
33 |
34 | # Parentheses preferences
35 | dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
36 | dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
37 | dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
38 | dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
39 |
40 | # Modifier preferences
41 | dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
42 |
43 | # Expression-level preferences
44 | csharp_style_deconstructed_variable_declaration = true:suggestion
45 | csharp_style_inlined_variable_declaration = true:suggestion
46 | csharp_style_throw_expression = true:suggestion
47 | dotnet_style_coalesce_expression = true:suggestion
48 | dotnet_style_collection_initializer = true:suggestion
49 | dotnet_style_explicit_tuple_names = true:suggestion
50 | dotnet_style_null_propagation = true:suggestion
51 | dotnet_style_object_initializer = true:suggestion
52 | dotnet_style_prefer_auto_properties = true:suggestion
53 | dotnet_style_prefer_compound_assignment = true:suggestion
54 | dotnet_style_prefer_conditional_expression_over_assignment = true:silent
55 | dotnet_style_prefer_conditional_expression_over_return = true:silent
56 | dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
57 | dotnet_style_prefer_inferred_tuple_names = true:suggestion
58 | dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
59 |
60 | # Field preferences
61 | dotnet_style_readonly_field = true:suggestion
62 |
63 | # Parameter preferences
64 | dotnet_code_quality_unused_parameters = all:suggestion
65 |
66 | #### C# Coding Conventions ####
67 |
68 | # var preferences
69 | csharp_style_var_elsewhere = false:silent
70 | csharp_style_var_for_built_in_types = true:silent
71 | csharp_style_var_when_type_is_apparent = true:silent
72 |
73 | # Expression-bodied members
74 | csharp_style_expression_bodied_accessors = true:silent
75 | csharp_style_expression_bodied_constructors = false:silent
76 | csharp_style_expression_bodied_indexers = true:silent
77 | csharp_style_expression_bodied_lambdas = true:silent
78 | csharp_style_expression_bodied_local_functions = false:silent
79 | csharp_style_expression_bodied_methods = false:silent
80 | csharp_style_expression_bodied_operators = false:silent
81 | csharp_style_expression_bodied_properties = true:silent
82 |
83 | # Pattern matching preferences
84 | csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
85 | csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
86 | csharp_style_prefer_switch_expression = true:suggestion
87 |
88 | # Null-checking preferences
89 | csharp_style_conditional_delegate_call = true:suggestion
90 |
91 | # Modifier preferences
92 | csharp_prefer_static_local_function = true:suggestion
93 | csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async
94 |
95 | # Code-block preferences
96 | csharp_prefer_braces = true:suggestion
97 | csharp_prefer_simple_using_statement = true:suggestion
98 |
99 | # Expression-level preferences
100 | csharp_prefer_simple_default_expression = true:suggestion
101 | csharp_style_pattern_local_over_anonymous_function = true:suggestion
102 | csharp_style_prefer_index_operator = true:suggestion
103 | csharp_style_prefer_range_operator = true:suggestion
104 | csharp_style_unused_value_assignment_preference = discard_variable:suggestion
105 | csharp_style_unused_value_expression_statement_preference = discard_variable:silent
106 |
107 | # 'using' directive preferences
108 | csharp_using_directive_placement = outside_namespace:silent
109 |
110 | #### C# Formatting Rules ####
111 |
112 | # New line preferences
113 | csharp_new_line_before_catch = true
114 | csharp_new_line_before_else = true
115 | csharp_new_line_before_finally = true
116 | csharp_new_line_before_members_in_anonymous_types = true
117 | csharp_new_line_before_members_in_object_initializers = true
118 | csharp_new_line_before_open_brace = all
119 | csharp_new_line_between_query_expression_clauses = true
120 |
121 | # Indentation preferences
122 | csharp_indent_block_contents = true
123 | csharp_indent_braces = false
124 | csharp_indent_case_contents = true
125 | csharp_indent_case_contents_when_block = true
126 | csharp_indent_labels = one_less_than_current
127 | csharp_indent_switch_labels = true
128 |
129 | # Space preferences
130 | csharp_space_after_cast = false
131 | csharp_space_after_colon_in_inheritance_clause = true
132 | csharp_space_after_comma = true
133 | csharp_space_after_dot = false
134 | csharp_space_after_keywords_in_control_flow_statements = true
135 | csharp_space_after_semicolon_in_for_statement = true
136 | csharp_space_around_binary_operators = before_and_after
137 | csharp_space_around_declaration_statements = false
138 | csharp_space_before_colon_in_inheritance_clause = true
139 | csharp_space_before_comma = false
140 | csharp_space_before_dot = false
141 | csharp_space_before_open_square_brackets = false
142 | csharp_space_before_semicolon_in_for_statement = false
143 | csharp_space_between_empty_square_brackets = false
144 | csharp_space_between_method_call_empty_parameter_list_parentheses = false
145 | csharp_space_between_method_call_name_and_opening_parenthesis = false
146 | csharp_space_between_method_call_parameter_list_parentheses = false
147 | csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
148 | csharp_space_between_method_declaration_name_and_open_parenthesis = false
149 | csharp_space_between_method_declaration_parameter_list_parentheses = false
150 | csharp_space_between_parentheses = false
151 | csharp_space_between_square_brackets = false
152 |
153 | # Wrapping preferences
154 | csharp_preserve_single_line_blocks = true
155 | csharp_preserve_single_line_statements = true
156 |
157 | #### Naming styles ####
158 |
159 | # Naming rules
160 |
161 | dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
162 | dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
163 | dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
164 |
165 | dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
166 | dotnet_naming_rule.types_should_be_pascal_case.symbols = types
167 | dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
168 |
169 | dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
170 | dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
171 | dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
172 |
173 | dotnet_naming_rule.constant_field_should_be_pascal_case.severity = suggestion
174 | dotnet_naming_rule.constant_field_should_be_pascal_case.symbols = constant_field
175 | dotnet_naming_rule.constant_field_should_be_pascal_case.style = pascal_case
176 |
177 | dotnet_naming_rule.static_field_should_be_pascal_case.severity = suggestion
178 | dotnet_naming_rule.static_field_should_be_pascal_case.symbols = static_field
179 | dotnet_naming_rule.static_field_should_be_pascal_case.style = pascal_case
180 |
181 | dotnet_naming_rule.private_or_internal_field_should_be_underscore_prefix.severity = warning
182 | dotnet_naming_rule.private_or_internal_field_should_be_underscore_prefix.symbols = private_or_internal_field
183 | dotnet_naming_rule.private_or_internal_field_should_be_underscore_prefix.style = underscore_prefix
184 |
185 | dotnet_naming_rule.parameter_should_be_prefixed_parameter.severity = silent
186 | dotnet_naming_rule.parameter_should_be_prefixed_parameter.symbols = parameter
187 | dotnet_naming_rule.parameter_should_be_prefixed_parameter.style = prefixed_parameter
188 |
189 | # Symbol specifications
190 |
191 | dotnet_naming_symbols.interface.applicable_kinds = interface
192 | dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal
193 | dotnet_naming_symbols.interface.required_modifiers =
194 |
195 | dotnet_naming_symbols.static_field.applicable_kinds = field
196 | dotnet_naming_symbols.static_field.applicable_accessibilities = public, internal, private, protected, protected_internal
197 | dotnet_naming_symbols.static_field.required_modifiers = static
198 |
199 | dotnet_naming_symbols.private_or_internal_field.applicable_kinds = field
200 | dotnet_naming_symbols.private_or_internal_field.applicable_accessibilities = internal, private
201 | dotnet_naming_symbols.private_or_internal_field.required_modifiers =
202 |
203 | dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
204 | dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal
205 | dotnet_naming_symbols.types.required_modifiers =
206 |
207 | dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
208 | dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal
209 | dotnet_naming_symbols.non_field_members.required_modifiers =
210 |
211 | dotnet_naming_symbols.constant_field.applicable_kinds = field
212 | dotnet_naming_symbols.constant_field.applicable_accessibilities = public, internal, private, protected, protected_internal
213 | dotnet_naming_symbols.constant_field.required_modifiers = const
214 |
215 | dotnet_naming_symbols.parameter.applicable_kinds = parameter
216 | dotnet_naming_symbols.parameter.applicable_accessibilities =
217 | dotnet_naming_symbols.parameter.required_modifiers =
218 |
219 | # Naming styles
220 |
221 | dotnet_naming_style.pascal_case.required_prefix =
222 | dotnet_naming_style.pascal_case.required_suffix =
223 | dotnet_naming_style.pascal_case.word_separator =
224 | dotnet_naming_style.pascal_case.capitalization = pascal_case
225 |
226 | dotnet_naming_style.begins_with_i.required_prefix = I
227 | dotnet_naming_style.begins_with_i.required_suffix =
228 | dotnet_naming_style.begins_with_i.word_separator =
229 | dotnet_naming_style.begins_with_i.capitalization = pascal_case
230 |
231 | dotnet_naming_style.underscore_prefix.required_prefix = _
232 | dotnet_naming_style.underscore_prefix.required_suffix =
233 | dotnet_naming_style.underscore_prefix.word_separator =
234 | dotnet_naming_style.underscore_prefix.capitalization = camel_case
235 |
236 | dotnet_naming_style.prefixed_parameter.required_prefix = p
237 | dotnet_naming_style.prefixed_parameter.required_suffix =
238 | dotnet_naming_style.prefixed_parameter.word_separator =
239 | dotnet_naming_style.prefixed_parameter.capitalization = pascal_case
240 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # To get started with Dependabot version updates, you'll need to specify which
2 | # package ecosystems to update and where the package manifests are located.
3 | # Please see the documentation for all configuration options:
4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5 |
6 | version: 2
7 | updates:
8 | - package-ecosystem: "nuget"
9 | directory: "/" # Location of package manifests
10 | schedule:
11 | interval: "weekly"
12 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Aa][Rr][Mm]/
27 | [Aa][Rr][Mm]64/
28 | bld/
29 | [Bb]in/
30 | [Oo]bj/
31 | [Ll]og/
32 | [Ll]ogs/
33 |
34 | # Visual Studio 2015/2017 cache/options directory
35 | .vs/
36 | # Uncomment if you have tasks that create the project's static files in wwwroot
37 | #wwwroot/
38 |
39 | # Visual Studio 2017 auto generated files
40 | Generated\ Files/
41 |
42 | # MSTest test Results
43 | [Tt]est[Rr]esult*/
44 | [Bb]uild[Ll]og.*
45 |
46 | # NUnit
47 | *.VisualState.xml
48 | TestResult.xml
49 | nunit-*.xml
50 |
51 | # Build Results of an ATL Project
52 | [Dd]ebugPS/
53 | [Rr]eleasePS/
54 | dlldata.c
55 |
56 | # Benchmark Results
57 | BenchmarkDotNet.Artifacts/
58 |
59 | # .NET Core
60 | project.lock.json
61 | project.fragment.lock.json
62 | artifacts/
63 |
64 | # StyleCop
65 | StyleCopReport.xml
66 |
67 | # Files built by Visual Studio
68 | *_i.c
69 | *_p.c
70 | *_h.h
71 | *.ilk
72 | *.meta
73 | *.obj
74 | *.iobj
75 | *.pch
76 | *.pdb
77 | *.ipdb
78 | *.pgc
79 | *.pgd
80 | *.rsp
81 | *.sbr
82 | *.tlb
83 | *.tli
84 | *.tlh
85 | *.tmp
86 | *.tmp_proj
87 | *_wpftmp.csproj
88 | *.log
89 | *.vspscc
90 | *.vssscc
91 | .builds
92 | *.pidb
93 | *.svclog
94 | *.scc
95 |
96 | # Chutzpah Test files
97 | _Chutzpah*
98 |
99 | # Visual C++ cache files
100 | ipch/
101 | *.aps
102 | *.ncb
103 | *.opendb
104 | *.opensdf
105 | *.sdf
106 | *.cachefile
107 | *.VC.db
108 | *.VC.VC.opendb
109 |
110 | # Visual Studio profiler
111 | *.psess
112 | *.vsp
113 | *.vspx
114 | *.sap
115 |
116 | # Visual Studio Trace Files
117 | *.e2e
118 |
119 | # TFS 2012 Local Workspace
120 | $tf/
121 |
122 | # Guidance Automation Toolkit
123 | *.gpState
124 |
125 | # ReSharper is a .NET coding add-in
126 | _ReSharper*/
127 | *.[Rr]e[Ss]harper
128 | *.DotSettings.user
129 |
130 | # TeamCity is a build add-in
131 | _TeamCity*
132 |
133 | # DotCover is a Code Coverage Tool
134 | *.dotCover
135 |
136 | # AxoCover is a Code Coverage Tool
137 | .axoCover/*
138 | !.axoCover/settings.json
139 |
140 | # Visual Studio code coverage results
141 | *.coverage
142 | *.coveragexml
143 |
144 | # NCrunch
145 | _NCrunch_*
146 | .*crunch*.local.xml
147 | nCrunchTemp_*
148 |
149 | # MightyMoose
150 | *.mm.*
151 | AutoTest.Net/
152 |
153 | # Web workbench (sass)
154 | .sass-cache/
155 |
156 | # Installshield output folder
157 | [Ee]xpress/
158 |
159 | # DocProject is a documentation generator add-in
160 | DocProject/buildhelp/
161 | DocProject/Help/*.HxT
162 | DocProject/Help/*.HxC
163 | DocProject/Help/*.hhc
164 | DocProject/Help/*.hhk
165 | DocProject/Help/*.hhp
166 | DocProject/Help/Html2
167 | DocProject/Help/html
168 |
169 | # Click-Once directory
170 | publish/
171 |
172 | # Publish Web Output
173 | *.[Pp]ublish.xml
174 | *.azurePubxml
175 | # Note: Comment the next line if you want to checkin your web deploy settings,
176 | # but database connection strings (with potential passwords) will be unencrypted
177 | *.pubxml
178 | *.publishproj
179 |
180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
181 | # checkin your Azure Web App publish settings, but sensitive information contained
182 | # in these scripts will be unencrypted
183 | PublishScripts/
184 |
185 | # NuGet Packages
186 | *.nupkg
187 | # NuGet Symbol Packages
188 | *.snupkg
189 | # The packages folder can be ignored because of Package Restore
190 | **/[Pp]ackages/*
191 | # except build/, which is used as an MSBuild target.
192 | !**/[Pp]ackages/build/
193 | # Uncomment if necessary however generally it will be regenerated when needed
194 | #!**/[Pp]ackages/repositories.config
195 | # NuGet v3's project.json files produces more ignorable files
196 | *.nuget.props
197 | *.nuget.targets
198 |
199 | # Microsoft Azure Build Output
200 | csx/
201 | *.build.csdef
202 |
203 | # Microsoft Azure Emulator
204 | ecf/
205 | rcf/
206 |
207 | # Windows Store app package directories and files
208 | AppPackages/
209 | BundleArtifacts/
210 | Package.StoreAssociation.xml
211 | _pkginfo.txt
212 | *.appx
213 | *.appxbundle
214 | *.appxupload
215 |
216 | # Visual Studio cache files
217 | # files ending in .cache can be ignored
218 | *.[Cc]ache
219 | # but keep track of directories ending in .cache
220 | !?*.[Cc]ache/
221 |
222 | # Others
223 | ClientBin/
224 | ~$*
225 | *~
226 | *.dbmdl
227 | *.dbproj.schemaview
228 | *.jfm
229 | *.pfx
230 | *.publishsettings
231 | orleans.codegen.cs
232 |
233 | # Including strong name files can present a security risk
234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
235 | #*.snk
236 |
237 | # Since there are multiple workflows, uncomment next line to ignore bower_components
238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
239 | #bower_components/
240 |
241 | # RIA/Silverlight projects
242 | Generated_Code/
243 |
244 | # Backup & report files from converting an old project file
245 | # to a newer Visual Studio version. Backup files are not needed,
246 | # because we have git ;-)
247 | _UpgradeReport_Files/
248 | Backup*/
249 | UpgradeLog*.XML
250 | UpgradeLog*.htm
251 | ServiceFabricBackup/
252 | *.rptproj.bak
253 |
254 | # SQL Server files
255 | *.mdf
256 | *.ldf
257 | *.ndf
258 |
259 | # Business Intelligence projects
260 | *.rdl.data
261 | *.bim.layout
262 | *.bim_*.settings
263 | *.rptproj.rsuser
264 | *- [Bb]ackup.rdl
265 | *- [Bb]ackup ([0-9]).rdl
266 | *- [Bb]ackup ([0-9][0-9]).rdl
267 |
268 | # Microsoft Fakes
269 | FakesAssemblies/
270 |
271 | # GhostDoc plugin setting file
272 | *.GhostDoc.xml
273 |
274 | # Node.js Tools for Visual Studio
275 | .ntvs_analysis.dat
276 | node_modules/
277 |
278 | # Visual Studio 6 build log
279 | *.plg
280 |
281 | # Visual Studio 6 workspace options file
282 | *.opt
283 |
284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
285 | *.vbw
286 |
287 | # Visual Studio LightSwitch build output
288 | **/*.HTMLClient/GeneratedArtifacts
289 | **/*.DesktopClient/GeneratedArtifacts
290 | **/*.DesktopClient/ModelManifest.xml
291 | **/*.Server/GeneratedArtifacts
292 | **/*.Server/ModelManifest.xml
293 | _Pvt_Extensions
294 |
295 | # Paket dependency manager
296 | .paket/paket.exe
297 | paket-files/
298 |
299 | # FAKE - F# Make
300 | .fake/
301 |
302 | # CodeRush personal settings
303 | .cr/personal
304 |
305 | # Python Tools for Visual Studio (PTVS)
306 | __pycache__/
307 | *.pyc
308 |
309 | # Cake - Uncomment if you are using it
310 | # tools/**
311 | # !tools/packages.config
312 |
313 | # Tabs Studio
314 | *.tss
315 |
316 | # Telerik's JustMock configuration file
317 | *.jmconfig
318 |
319 | # BizTalk build output
320 | *.btp.cs
321 | *.btm.cs
322 | *.odx.cs
323 | *.xsd.cs
324 |
325 | # OpenCover UI analysis results
326 | OpenCover/
327 |
328 | # Azure Stream Analytics local run output
329 | ASALocalRun/
330 |
331 | # MSBuild Binary and Structured Log
332 | *.binlog
333 |
334 | # NVidia Nsight GPU debugger configuration file
335 | *.nvuser
336 |
337 | # MFractors (Xamarin productivity tool) working folder
338 | .mfractor/
339 |
340 | # Local History for Visual Studio
341 | .localhistory/
342 |
343 | # BeatPulse healthcheck temp database
344 | healthchecksdb
345 |
346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
347 | MigrationBackup/
348 |
349 | # Ionide (cross platform F# VS Code tools) working folder
350 | .ionide/
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2012 Mauricio DIAZ ORLICH
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/Madd0.AzureStorageDriver.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29509.3
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Madd0.AzureStorageDriver", "Madd0.AzureStorageDriver\Madd0.AzureStorageDriver.csproj", "{33CB981E-3A8D-4949-9B34-F7F0B6B5891F}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{60F155B6-550D-41F3-A8DB-67ECA237869C}"
9 | ProjectSection(SolutionItems) = preProject
10 | LICENSE.md = LICENSE.md
11 | README.md = README.md
12 | EndProjectSection
13 | EndProject
14 | Global
15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
16 | Debug|Any CPU = Debug|Any CPU
17 | Release|Any CPU = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
20 | {33CB981E-3A8D-4949-9B34-F7F0B6B5891F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {33CB981E-3A8D-4949-9B34-F7F0B6B5891F}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {33CB981E-3A8D-4949-9B34-F7F0B6B5891F}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {33CB981E-3A8D-4949-9B34-F7F0B6B5891F}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {887BB131-BC0A-45C2-A971-797FC9825D8C}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/Madd0.AzureStorageDriver/AzureDriver.cs:
--------------------------------------------------------------------------------
1 | //-----------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2012 Mauricio DIAZ ORLICH.
4 | // Code licensed under the MIT X11 license.
5 | //
6 | // Mauricio DIAZ ORLICH
7 | //-----------------------------------------------------------------------
8 |
9 | namespace Madd0.AzureStorageDriver
10 | {
11 | using System;
12 | using System.Collections.Generic;
13 | using System.Reflection;
14 | using LINQPad.Extensibility.DataContext;
15 | using Madd0.AzureStorageDriver.Properties;
16 | #if NETCORE
17 | using Microsoft.Azure.Cosmos.Table;
18 | #else
19 | using Microsoft.Azure.CosmosDB.Table;
20 | #endif
21 |
22 | ///
23 | /// LINQPad dynamic driver that lets users connect to an Azure Table Storage account.
24 | ///
25 | public class AzureDriver : DynamicDataContextDriver
26 | {
27 | #if DEBUG
28 | static AzureDriver()
29 | {
30 | AppDomain.CurrentDomain.FirstChanceException += (sender, args) =>
31 | {
32 | if (args.Exception.StackTrace.Contains(typeof(AzureDriver).Namespace))
33 | {
34 | System.Diagnostics.Debugger.Launch();
35 | }
36 | };
37 |
38 | }
39 | #endif
40 | ///
41 | /// Gets the name of the driver author.
42 | ///
43 | public override string Author
44 | {
45 | get { return Resources.AuthorName; }
46 | }
47 |
48 | ///
49 | /// Gets the name of the driver.
50 | ///
51 | public override string Name
52 | {
53 | get { return Resources.DriverName; }
54 | }
55 |
56 | /// Gets the text to display in the root Schema Explorer node for a given connection info.
57 | /// The connection information.
58 | /// The text to display in the root Schema Explorer node for a given connection info
59 | public override string GetConnectionDescription(IConnectionInfo cxInfo)
60 | {
61 | var accountProperties = new StorageAccountProperties(cxInfo);
62 |
63 | var description = accountProperties.DisplayName;
64 |
65 | if (accountProperties.AzureEnvironment != AzureEnvironment.AzureGlobalCloud)
66 | {
67 | description += $" ({accountProperties.AzureEnvironment.Name})";
68 | }
69 |
70 | return description;
71 | }
72 |
73 | ///
74 | /// Shows the connection dialog.
75 | ///
76 | /// The connection info.
77 | /// if set to true [is new connection].
78 | ///
79 | public override bool ShowConnectionDialog(IConnectionInfo cxInfo, ConnectionDialogOptions dialogOptions)
80 | {
81 | if (dialogOptions.IsNewConnection)
82 | {
83 | _ = new StorageAccountProperties(cxInfo)
84 | {
85 | UseHttps = true,
86 | NumberOfRows = 100
87 | };
88 | }
89 |
90 | bool? result = new ConnectionDialog(cxInfo).ShowDialog();
91 | return result == true;
92 | }
93 |
94 | ///
95 | /// Determines whether two repositories are equivalent.
96 | ///
97 | /// The connection information of the first repository.
98 | /// The connection information of the second repository.
99 | /// true if both repositories use the same account name; false otherwise.
100 | public override bool AreRepositoriesEquivalent(IConnectionInfo c1, IConnectionInfo c2)
101 | {
102 | var account1 = (string)c1.DriverData.Element("AccountName") ?? string.Empty;
103 | var account2 = (string)c2.DriverData.Element("AccountName") ?? string.Empty;
104 |
105 | return account1.Equals(account2);
106 | }
107 |
108 | #if NETCORE
109 | public override IEnumerable GetAssembliesToAdd(IConnectionInfo cxInfo)
110 | {
111 | return new string[]
112 | {
113 | "Microsoft.Azure.Cosmos.Table.dll"
114 | };
115 | }
116 | #else
117 | public override IEnumerable GetAssembliesToAdd(IConnectionInfo cxInfo)
118 | {
119 | return new string[]
120 | {
121 | "Microsoft.Azure.CosmosDB.Table.dll"
122 | };
123 | }
124 | #endif
125 | ///
126 | /// Gets the schema and builds the assembly that contains the typed data context.
127 | ///
128 | /// The connection information.
129 | /// The assembly to build.
130 | /// The namespace to be used in the generated code.
131 | /// Name of the type of the typed data context.
132 | /// A list of instaces that describes the current schema.
133 | public override List GetSchemaAndBuildAssembly(IConnectionInfo cxInfo, AssemblyName assemblyToBuild, ref string nameSpace, ref string typeName)
134 | {
135 | // The helper class SchemaBuilder will do the heavy lifting
136 | return SchemaBuilder.GetSchemaAndBuildAssembly(
137 | new StorageAccountProperties(cxInfo),
138 | assemblyToBuild,
139 | nameSpace,
140 | typeName);
141 | }
142 |
143 | ///
144 | /// Gets the context constructor arguments.
145 | ///
146 | /// The connection info.
147 | /// An ordered collection of objects to pass to the data context as arguments.
148 | public override object[] GetContextConstructorArguments(IConnectionInfo cxInfo)
149 | {
150 | var properties = new StorageAccountProperties(cxInfo);
151 |
152 | var storageAccount = properties.GetStorageAccount();
153 |
154 | return new object[]
155 | {
156 | storageAccount.CreateCloudTableClient()
157 | };
158 | }
159 |
160 | ///
161 | /// Gets the context constructor parameters.
162 | ///
163 | /// The connection info.
164 | /// A list of objects that describe the parameters
165 | /// of the typed data context's constructor.
166 | public override ParameterDescriptor[] GetContextConstructorParameters(IConnectionInfo cxInfo)
167 | {
168 | return new[]
169 | {
170 | new ParameterDescriptor("client", typeof(CloudTableClient).FullName)
171 | };
172 | }
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/Madd0.AzureStorageDriver/Compiler/CodeDomCompiler.cs:
--------------------------------------------------------------------------------
1 | //-----------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2012 Mauricio DIAZ ORLICH.
4 | // Code licensed under the MIT X11 license.
5 | //
6 | // Mauricio DIAZ ORLICH
7 | //-----------------------------------------------------------------------
8 |
9 | #if !NETCORE
10 | namespace Madd0.AzureStorageDriver
11 | {
12 | using Madd0.AzureStorageDriver.Properties;
13 | using Microsoft.CSharp;
14 | using System;
15 | using System.CodeDom.Compiler;
16 | using System.Collections.Generic;
17 | using System.Linq;
18 | using System.Reflection;
19 |
20 | internal class CodeDomCompiler : ICompiler
21 | {
22 | public void Compile(string code, AssemblyName name, IEnumerable assemblyLocations)
23 | {
24 | CompilerResults results;
25 |
26 | var path = name.CodeBase;
27 |
28 | var dependencies = assemblyLocations.ToArray();
29 |
30 | using (var codeProvider = new CSharpCodeProvider())
31 | {
32 | #if DEBUG
33 | var options = new CompilerParameters(dependencies, path, true);
34 | #else
35 | var options = new CompilerParameters(dependencies, path, false);
36 | #endif
37 | results = codeProvider.CompileAssemblyFromSource(options, code);
38 | }
39 |
40 | if (results.Errors.Count > 0)
41 | {
42 | throw new ArgumentException(string.Format(Exceptions.CannotCompileCode, results.Errors[0].ErrorText, results.Errors[0].Line));
43 | }
44 | }
45 | }
46 | }
47 | #endif
--------------------------------------------------------------------------------
/Madd0.AzureStorageDriver/Compiler/ICompiler.cs:
--------------------------------------------------------------------------------
1 | //-----------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2012 Mauricio DIAZ ORLICH.
4 | // Code licensed under the MIT X11 license.
5 | //
6 | // Mauricio DIAZ ORLICH
7 | //-----------------------------------------------------------------------
8 |
9 | namespace Madd0.AzureStorageDriver
10 | {
11 | using System.Collections.Generic;
12 | using System.Reflection;
13 |
14 | internal interface ICompiler
15 | {
16 | void Compile(string code, AssemblyName name, IEnumerable assemblyLocations);
17 | }
18 | }
--------------------------------------------------------------------------------
/Madd0.AzureStorageDriver/Compiler/RoslynCompiler.cs:
--------------------------------------------------------------------------------
1 | //-----------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2012 Mauricio DIAZ ORLICH.
4 | // Code licensed under the MIT X11 license.
5 | //
6 | // Mauricio DIAZ ORLICH
7 | //-----------------------------------------------------------------------
8 |
9 | #if NETCORE
10 |
11 | namespace Madd0.AzureStorageDriver
12 | {
13 | using LINQPad.Extensibility.DataContext;
14 | using Madd0.AzureStorageDriver.Properties;
15 | using Microsoft.CodeAnalysis;
16 | using Microsoft.CodeAnalysis.CSharp;
17 | using System;
18 | using System.Collections.Generic;
19 | using System.IO;
20 | using System.Linq;
21 | using System.Reflection;
22 |
23 | internal class RoslynCompiler : ICompiler
24 | {
25 | public CSharpCompilationOptions Options { get; } = new CSharpCompilationOptions(
26 | OutputKind.DynamicallyLinkedLibrary,
27 | reportSuppressedDiagnostics: true,
28 | #if DEBUG
29 | optimizationLevel: OptimizationLevel.Debug,
30 | #else
31 | optimizationLevel: OptimizationLevel.Release,
32 | #endif
33 | generalDiagnosticOption: ReportDiagnostic.Error
34 | );
35 |
36 | public void Compile(string code, AssemblyName name, IEnumerable assemblyLocations)
37 | {
38 | var platformAssemblies = DataContextDriver.GetCoreFxReferenceAssemblies();
39 |
40 | var references = platformAssemblies.Concat(assemblyLocations).Select(l => MetadataReference.CreateFromFile(l));
41 |
42 | var parseOptions = new CSharpParseOptions().WithPreprocessorSymbols("NETCORE");
43 |
44 | var compilation = CSharpCompilation.Create(
45 | name.Name,
46 | references: references,
47 | syntaxTrees: new SyntaxTree[] { CSharpSyntaxTree.ParseText(code, parseOptions) },
48 | options: this.Options
49 | );
50 |
51 | using var fileStream = File.OpenWrite(name.CodeBase);
52 |
53 | var results = compilation.Emit(fileStream);
54 |
55 | if (!results.Success)
56 | {
57 | throw new ArgumentException(string.Format(Exceptions.CannotCompileCode, results.Diagnostics[0].GetMessage(), results.Diagnostics[0].Location.GetLineSpan()));
58 | }
59 | }
60 | }
61 | }
62 |
63 | #endif
--------------------------------------------------------------------------------
/Madd0.AzureStorageDriver/ConnectionDialog.xaml:
--------------------------------------------------------------------------------
1 |
13 |
14 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
35 |
39 |
40 |
41 |
42 |
45 |
46 |
50 |
51 |
52 |
53 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
83 |
84 |
89 |
90 |
95 |
103 |
107 |
108 |
109 | The number of lines that will be read in order to determine the schema of an Azure Table.
110 |
111 |
112 |
115 |
120 |
121 |
122 |
127 |
135 |
139 |
140 |
141 | The number of concurrent calls that will be made to Azure Table Storage to determine the columns available for each table.
142 |
143 |
144 |
147 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
164 |
165 |
166 |
172 |
178 |
179 |
180 |
--------------------------------------------------------------------------------
/Madd0.AzureStorageDriver/ConnectionDialog.xaml.cs:
--------------------------------------------------------------------------------
1 | //-----------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2012 Mauricio DIAZ ORLICH.
4 | // Code licensed under the MIT X11 license.
5 | //
6 | // Mauricio DIAZ ORLICH
7 | //-----------------------------------------------------------------------
8 |
9 | namespace Madd0.AzureStorageDriver
10 | {
11 | using System;
12 | using System.Runtime.InteropServices;
13 | using System.Windows;
14 | using System.Windows.Interop;
15 | using LINQPad.Extensibility.DataContext;
16 |
17 | ///
18 | /// Interaction logic for ConnectionDialog.xaml
19 | ///
20 | public partial class ConnectionDialog : Window
21 | {
22 | ///
23 | /// Initializes a new instance of the class.
24 | ///
25 | /// The connection info.
26 | public ConnectionDialog(IConnectionInfo connectionInfo)
27 | {
28 | InitializeComponent();
29 |
30 | DataContext = new StorageAccountProperties(connectionInfo);
31 | }
32 |
33 | ///
34 | /// Raises the event.
35 | ///
36 | /// An that contains the event data.
37 | protected override void OnSourceInitialized(EventArgs e)
38 | {
39 | IntPtr hwnd = new WindowInteropHelper(this).Handle;
40 |
41 | // Change the window style to remove icon and buttons
42 | SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & (0xFFFFFFFF ^ WS_SYSMENU));
43 |
44 | base.OnSourceInitialized(e);
45 | }
46 |
47 | ///
48 | /// Called when the OK button is clicked.
49 | ///
50 | /// The sender.
51 | /// The instance containing the event data.
52 | private void OnOkClick(object sender, RoutedEventArgs e)
53 | {
54 | this.DialogResult = true;
55 | }
56 |
57 | #region p/invoke
58 |
59 | [DllImport("user32.dll")]
60 | private static extern uint GetWindowLong(IntPtr hWnd, int nIndex);
61 |
62 | [DllImport("user32.dll")]
63 | private static extern int SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong);
64 |
65 | private const int GWL_STYLE = -16;
66 |
67 | private const uint WS_SYSMENU = 0x80000;
68 |
69 | #endregion
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/Madd0.AzureStorageDriver/DataContextTemplate.cs:
--------------------------------------------------------------------------------
1 | // ------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version: 16.0.0.0
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | // ------------------------------------------------------------------------------
10 | namespace Madd0.AzureStorageDriver
11 | {
12 | using System;
13 | using System.Collections;
14 | using System.Collections.Generic;
15 |
16 | ///
17 | /// Class to produce the template output
18 | ///
19 |
20 | #line 1 "C:\Projects\AzureStorageDriver\Madd0.AzureStorageDriver\DataContextTemplate.tt"
21 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")]
22 | public partial class DataContextTemplate : DataContextTemplateBase
23 | {
24 | #line hidden
25 | ///
26 | /// Create the template output
27 | ///
28 | public virtual string TransformText()
29 | {
30 | this.Write("\r\nnamespace ");
31 |
32 | #line 6 "C:\Projects\AzureStorageDriver\Madd0.AzureStorageDriver\DataContextTemplate.tt"
33 | this.Write(this.ToStringHelper.ToStringWithCulture(this.Namespace));
34 |
35 | #line default
36 | #line hidden
37 | this.Write(@"
38 | {
39 | using System;
40 | using System.Collections;
41 | using System.Collections.Generic;
42 | using System.Linq;
43 | using Madd0.UserQuery;
44 | #if NETCORE
45 | using Microsoft.Azure.Cosmos.Table;
46 | #else
47 | using Microsoft.Azure.CosmosDB.Table;
48 | #endif
49 |
50 | public class ");
51 |
52 | #line 19 "C:\Projects\AzureStorageDriver\Madd0.AzureStorageDriver\DataContextTemplate.tt"
53 | this.Write(this.ToStringHelper.ToStringWithCulture(this.TypeName));
54 |
55 | #line default
56 | #line hidden
57 | this.Write("\r\n {\r\n public ");
58 |
59 | #line 21 "C:\Projects\AzureStorageDriver\Madd0.AzureStorageDriver\DataContextTemplate.tt"
60 | this.Write(this.ToStringHelper.ToStringWithCulture(this.TypeName));
61 |
62 | #line default
63 | #line hidden
64 | this.Write("(CloudTableClient client)\r\n {\r\n this.TableClient = client;\r\n " +
65 | " }\r\n\r\n public CloudTableClient TableClient\r\n {\r\n g" +
66 | "et;\r\n private set;\r\n }\r\n\r\n");
67 |
68 | #line 32 "C:\Projects\AzureStorageDriver\Madd0.AzureStorageDriver\DataContextTemplate.tt"
69 |
70 | foreach (var table in this.Tables)
71 | {
72 |
73 |
74 | #line default
75 | #line hidden
76 | this.Write(" public ExtendedTableQuery<");
77 |
78 | #line 36 "C:\Projects\AzureStorageDriver\Madd0.AzureStorageDriver\DataContextTemplate.tt"
79 | this.Write(this.ToStringHelper.ToStringWithCulture(table.Name));
80 |
81 | #line default
82 | #line hidden
83 | this.Write("Entity> ");
84 |
85 | #line 36 "C:\Projects\AzureStorageDriver\Madd0.AzureStorageDriver\DataContextTemplate.tt"
86 | this.Write(this.ToStringHelper.ToStringWithCulture(table.Name));
87 |
88 | #line default
89 | #line hidden
90 | this.Write("\r\n {\r\n get\r\n {\r\n return new ExtendedT" +
91 | "ableQuery<");
92 |
93 | #line 40 "C:\Projects\AzureStorageDriver\Madd0.AzureStorageDriver\DataContextTemplate.tt"
94 | this.Write(this.ToStringHelper.ToStringWithCulture(table.Name));
95 |
96 | #line default
97 | #line hidden
98 | this.Write("Entity>(this.TableClient.GetTableReference(\"");
99 |
100 | #line 40 "C:\Projects\AzureStorageDriver\Madd0.AzureStorageDriver\DataContextTemplate.tt"
101 | this.Write(this.ToStringHelper.ToStringWithCulture(table.Name));
102 |
103 | #line default
104 | #line hidden
105 | this.Write("\"));\r\n }\r\n }\r\n");
106 |
107 | #line 43 "C:\Projects\AzureStorageDriver\Madd0.AzureStorageDriver\DataContextTemplate.tt"
108 |
109 | }
110 |
111 |
112 | #line default
113 | #line hidden
114 | this.Write("\r\n public TableQuery MakeTableQuery()\r\n whe" +
115 | "re TElement : ITableEntity\r\n {\r\n return new TableQuery();\r\n }\r\n }\r\n\r\n");
117 |
118 | #line 54 "C:\Projects\AzureStorageDriver\Madd0.AzureStorageDriver\DataContextTemplate.tt"
119 |
120 | foreach (var table in this.Tables)
121 | {
122 |
123 |
124 | #line default
125 | #line hidden
126 | this.Write(" public class ");
127 |
128 | #line 58 "C:\Projects\AzureStorageDriver\Madd0.AzureStorageDriver\DataContextTemplate.tt"
129 | this.Write(this.ToStringHelper.ToStringWithCulture(table.Name));
130 |
131 | #line default
132 | #line hidden
133 | this.Write("Entity : TableEntity\r\n {\r\n ");
134 |
135 | #line 60 "C:\Projects\AzureStorageDriver\Madd0.AzureStorageDriver\DataContextTemplate.tt"
136 |
137 | foreach (var column in table.Columns)
138 | {
139 | if (!this.DefaultProperties.Contains(column.Name))
140 | {
141 |
142 |
143 | #line default
144 | #line hidden
145 | this.Write(" public ");
146 |
147 | #line 66 "C:\Projects\AzureStorageDriver\Madd0.AzureStorageDriver\DataContextTemplate.tt"
148 | this.Write(this.ToStringHelper.ToStringWithCulture(column.TypeName));
149 |
150 | #line default
151 | #line hidden
152 | this.Write(" ");
153 |
154 | #line 66 "C:\Projects\AzureStorageDriver\Madd0.AzureStorageDriver\DataContextTemplate.tt"
155 | this.Write(this.ToStringHelper.ToStringWithCulture(column.Name));
156 |
157 | #line default
158 | #line hidden
159 | this.Write("\r\n {\r\n get;\r\n set;\r\n }\r\n ");
160 |
161 | #line 71 "C:\Projects\AzureStorageDriver\Madd0.AzureStorageDriver\DataContextTemplate.tt"
162 |
163 | }
164 | }
165 |
166 |
167 | #line default
168 | #line hidden
169 | this.Write(" }\r\n");
170 |
171 | #line 76 "C:\Projects\AzureStorageDriver\Madd0.AzureStorageDriver\DataContextTemplate.tt"
172 |
173 | }
174 |
175 |
176 | #line default
177 | #line hidden
178 | this.Write("}\r\n\r\n");
179 | return this.GenerationEnvironment.ToString();
180 | }
181 |
182 | #line 81 "C:\Projects\AzureStorageDriver\Madd0.AzureStorageDriver\DataContextTemplate.tt"
183 |
184 | private readonly List DefaultProperties = new List { "PartitionKey", "RowKey", "Timestamp", "ETag" };
185 |
186 | public string Namespace { get; set; }
187 |
188 | public string TypeName { get; set; }
189 |
190 | public IEnumerable Tables { get; set; }
191 |
192 |
193 | #line default
194 | #line hidden
195 | }
196 |
197 | #line default
198 | #line hidden
199 | #region Base class
200 | ///
201 | /// Base class for this transformation
202 | ///
203 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")]
204 | public class DataContextTemplateBase
205 | {
206 | #region Fields
207 | private global::System.Text.StringBuilder generationEnvironmentField;
208 | private global::System.CodeDom.Compiler.CompilerErrorCollection errorsField;
209 | private global::System.Collections.Generic.List indentLengthsField;
210 | private string currentIndentField = "";
211 | private bool endsWithNewline;
212 | private global::System.Collections.Generic.IDictionary sessionField;
213 | #endregion
214 | #region Properties
215 | ///
216 | /// The string builder that generation-time code is using to assemble generated output
217 | ///
218 | protected System.Text.StringBuilder GenerationEnvironment
219 | {
220 | get
221 | {
222 | if ((this.generationEnvironmentField == null))
223 | {
224 | this.generationEnvironmentField = new global::System.Text.StringBuilder();
225 | }
226 | return this.generationEnvironmentField;
227 | }
228 | set
229 | {
230 | this.generationEnvironmentField = value;
231 | }
232 | }
233 | ///
234 | /// The error collection for the generation process
235 | ///
236 | public System.CodeDom.Compiler.CompilerErrorCollection Errors
237 | {
238 | get
239 | {
240 | if ((this.errorsField == null))
241 | {
242 | this.errorsField = new global::System.CodeDom.Compiler.CompilerErrorCollection();
243 | }
244 | return this.errorsField;
245 | }
246 | }
247 | ///
248 | /// A list of the lengths of each indent that was added with PushIndent
249 | ///
250 | private System.Collections.Generic.List indentLengths
251 | {
252 | get
253 | {
254 | if ((this.indentLengthsField == null))
255 | {
256 | this.indentLengthsField = new global::System.Collections.Generic.List();
257 | }
258 | return this.indentLengthsField;
259 | }
260 | }
261 | ///
262 | /// Gets the current indent we use when adding lines to the output
263 | ///
264 | public string CurrentIndent
265 | {
266 | get
267 | {
268 | return this.currentIndentField;
269 | }
270 | }
271 | ///
272 | /// Current transformation session
273 | ///
274 | public virtual global::System.Collections.Generic.IDictionary Session
275 | {
276 | get
277 | {
278 | return this.sessionField;
279 | }
280 | set
281 | {
282 | this.sessionField = value;
283 | }
284 | }
285 | #endregion
286 | #region Transform-time helpers
287 | ///
288 | /// Write text directly into the generated output
289 | ///
290 | public void Write(string textToAppend)
291 | {
292 | if (string.IsNullOrEmpty(textToAppend))
293 | {
294 | return;
295 | }
296 | // If we're starting off, or if the previous text ended with a newline,
297 | // we have to append the current indent first.
298 | if (((this.GenerationEnvironment.Length == 0)
299 | || this.endsWithNewline))
300 | {
301 | this.GenerationEnvironment.Append(this.currentIndentField);
302 | this.endsWithNewline = false;
303 | }
304 | // Check if the current text ends with a newline
305 | if (textToAppend.EndsWith(global::System.Environment.NewLine, global::System.StringComparison.CurrentCulture))
306 | {
307 | this.endsWithNewline = true;
308 | }
309 | // This is an optimization. If the current indent is "", then we don't have to do any
310 | // of the more complex stuff further down.
311 | if ((this.currentIndentField.Length == 0))
312 | {
313 | this.GenerationEnvironment.Append(textToAppend);
314 | return;
315 | }
316 | // Everywhere there is a newline in the text, add an indent after it
317 | textToAppend = textToAppend.Replace(global::System.Environment.NewLine, (global::System.Environment.NewLine + this.currentIndentField));
318 | // If the text ends with a newline, then we should strip off the indent added at the very end
319 | // because the appropriate indent will be added when the next time Write() is called
320 | if (this.endsWithNewline)
321 | {
322 | this.GenerationEnvironment.Append(textToAppend, 0, (textToAppend.Length - this.currentIndentField.Length));
323 | }
324 | else
325 | {
326 | this.GenerationEnvironment.Append(textToAppend);
327 | }
328 | }
329 | ///
330 | /// Write text directly into the generated output
331 | ///
332 | public void WriteLine(string textToAppend)
333 | {
334 | this.Write(textToAppend);
335 | this.GenerationEnvironment.AppendLine();
336 | this.endsWithNewline = true;
337 | }
338 | ///
339 | /// Write formatted text directly into the generated output
340 | ///
341 | public void Write(string format, params object[] args)
342 | {
343 | this.Write(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args));
344 | }
345 | ///
346 | /// Write formatted text directly into the generated output
347 | ///
348 | public void WriteLine(string format, params object[] args)
349 | {
350 | this.WriteLine(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args));
351 | }
352 | ///
353 | /// Raise an error
354 | ///
355 | public void Error(string message)
356 | {
357 | System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError();
358 | error.ErrorText = message;
359 | this.Errors.Add(error);
360 | }
361 | ///
362 | /// Raise a warning
363 | ///
364 | public void Warning(string message)
365 | {
366 | System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError();
367 | error.ErrorText = message;
368 | error.IsWarning = true;
369 | this.Errors.Add(error);
370 | }
371 | ///
372 | /// Increase the indent
373 | ///
374 | public void PushIndent(string indent)
375 | {
376 | if ((indent == null))
377 | {
378 | throw new global::System.ArgumentNullException("indent");
379 | }
380 | this.currentIndentField = (this.currentIndentField + indent);
381 | this.indentLengths.Add(indent.Length);
382 | }
383 | ///
384 | /// Remove the last indent that was added with PushIndent
385 | ///
386 | public string PopIndent()
387 | {
388 | string returnValue = "";
389 | if ((this.indentLengths.Count > 0))
390 | {
391 | int indentLength = this.indentLengths[(this.indentLengths.Count - 1)];
392 | this.indentLengths.RemoveAt((this.indentLengths.Count - 1));
393 | if ((indentLength > 0))
394 | {
395 | returnValue = this.currentIndentField.Substring((this.currentIndentField.Length - indentLength));
396 | this.currentIndentField = this.currentIndentField.Remove((this.currentIndentField.Length - indentLength));
397 | }
398 | }
399 | return returnValue;
400 | }
401 | ///
402 | /// Remove any indentation
403 | ///
404 | public void ClearIndent()
405 | {
406 | this.indentLengths.Clear();
407 | this.currentIndentField = "";
408 | }
409 | #endregion
410 | #region ToString Helpers
411 | ///
412 | /// Utility class to produce culture-oriented representation of an object as a string.
413 | ///
414 | public class ToStringInstanceHelper
415 | {
416 | private System.IFormatProvider formatProviderField = global::System.Globalization.CultureInfo.InvariantCulture;
417 | ///
418 | /// Gets or sets format provider to be used by ToStringWithCulture method.
419 | ///
420 | public System.IFormatProvider FormatProvider
421 | {
422 | get
423 | {
424 | return this.formatProviderField ;
425 | }
426 | set
427 | {
428 | if ((value != null))
429 | {
430 | this.formatProviderField = value;
431 | }
432 | }
433 | }
434 | ///
435 | /// This is called from the compile/run appdomain to convert objects within an expression block to a string
436 | ///
437 | public string ToStringWithCulture(object objectToConvert)
438 | {
439 | if ((objectToConvert == null))
440 | {
441 | throw new global::System.ArgumentNullException("objectToConvert");
442 | }
443 | System.Type t = objectToConvert.GetType();
444 | System.Reflection.MethodInfo method = t.GetMethod("ToString", new System.Type[] {
445 | typeof(System.IFormatProvider)});
446 | if ((method == null))
447 | {
448 | return objectToConvert.ToString();
449 | }
450 | else
451 | {
452 | return ((string)(method.Invoke(objectToConvert, new object[] {
453 | this.formatProviderField })));
454 | }
455 | }
456 | }
457 | private ToStringInstanceHelper toStringHelperField = new ToStringInstanceHelper();
458 | ///
459 | /// Helper to produce culture-oriented representation of an object as a string
460 | ///
461 | public ToStringInstanceHelper ToStringHelper
462 | {
463 | get
464 | {
465 | return this.toStringHelperField;
466 | }
467 | }
468 | #endregion
469 | }
470 | #endregion
471 | }
472 |
--------------------------------------------------------------------------------
/Madd0.AzureStorageDriver/DataContextTemplate.tt:
--------------------------------------------------------------------------------
1 | <#@ template debug="false" hostspecific="false" language="C#" #>
2 | <#@ import namespace="System" #>
3 | <#@ import namespace="System.Collections" #>
4 | <#@ import namespace="System.Collections.Generic" #>
5 |
6 | namespace <#= this.Namespace #>
7 | {
8 | using System;
9 | using System.Collections;
10 | using System.Collections.Generic;
11 | using System.Linq;
12 | using Madd0.UserQuery;
13 | #if NETCORE
14 | using Microsoft.Azure.Cosmos.Table;
15 | #else
16 | using Microsoft.Azure.CosmosDB.Table;
17 | #endif
18 |
19 | public class <#= this.TypeName #>
20 | {
21 | public <#= this.TypeName #>(CloudTableClient client)
22 | {
23 | this.TableClient = client;
24 | }
25 |
26 | public CloudTableClient TableClient
27 | {
28 | get;
29 | private set;
30 | }
31 |
32 | <#
33 | foreach (var table in this.Tables)
34 | {
35 | #>
36 | public ExtendedTableQuery<<#= table.Name #>Entity> <#= table.Name #>
37 | {
38 | get
39 | {
40 | return new ExtendedTableQuery<<#= table.Name #>Entity>(this.TableClient.GetTableReference("<#= table.Name #>"));
41 | }
42 | }
43 | <#
44 | }
45 | #>
46 |
47 | public TableQuery MakeTableQuery()
48 | where TElement : ITableEntity
49 | {
50 | return new TableQuery();
51 | }
52 | }
53 |
54 | <#
55 | foreach (var table in this.Tables)
56 | {
57 | #>
58 | public class <#= table.Name #>Entity : TableEntity
59 | {
60 | <#
61 | foreach (var column in table.Columns)
62 | {
63 | if (!this.DefaultProperties.Contains(column.Name))
64 | {
65 | #>
66 | public <#= column.TypeName #> <#= column.Name #>
67 | {
68 | get;
69 | set;
70 | }
71 | <#
72 | }
73 | }
74 | #>
75 | }
76 | <#
77 | }
78 | #>
79 | }
80 |
81 | <#+
82 | private readonly List DefaultProperties = new List { "PartitionKey", "RowKey", "Timestamp", "ETag" };
83 |
84 | public string Namespace { get; set; }
85 |
86 | public string TypeName { get; set; }
87 |
88 | public IEnumerable Tables { get; set; }
89 | #>
--------------------------------------------------------------------------------
/Madd0.AzureStorageDriver/Madd0.AzureStorageDriver.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | netcoreapp3.1;net46
4 | latest
5 | true
6 | Madd0.AzureStorageDriver
7 | true
8 | linqpaddriver
9 |
10 |
11 |
12 | AzureStorageDriver
13 | A LINQPad driver to perform queries against Azure Table Storage.
14 | madd0 (http://www.madd0.com)
15 | Azure Table Storage Driver
16 | Azure Table Storage Driver
17 | Copyright © 2012 Mauricio DIAZ ORLICH
18 | 2.1.2
19 | 2.1.2.0
20 | 2.1.2.0
21 | LICENSE.md
22 | https://github.com/madd0/AzureStorageDriver
23 | https://github.com/madd0/AzureStorageDriver.git
24 | git
25 | Mauricio Díaz Orlich
26 | True
27 | snupkg
28 |
29 |
30 |
31 | NETCORE
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | 4.0
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | 1.0.8
52 |
53 |
54 |
55 |
56 |
57 |
58 | 2.1.2
59 |
60 |
61 | PreserveNewest
62 |
63 |
64 |
65 |
66 |
67 | TextTemplatingFilePreprocessor
68 | DataContextTemplate.cs
69 |
70 |
71 | True
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | True
84 | True
85 | DataContextTemplate.tt
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/Madd0.AzureStorageDriver/Model/AzureEnvironment.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 |
5 | namespace Madd0.AzureStorageDriver
6 | {
7 | // From: https://github.com/Azure/azure-libraries-for-net/blob/master/src/ResourceManagement/ResourceManager/AzureEnvironment.cs
8 | public class AzureEnvironment
9 | {
10 | static AzureEnvironment()
11 | {
12 | AzureGlobalCloud = new AzureEnvironment()
13 | {
14 | Name = "Global Cloud",
15 | AuthenticationEndpoint = "https://login.microsoftonline.com/",
16 | ResourceManagerEndpoint = "https://management.azure.com/",
17 | ManagementEndpoint = "https://management.core.windows.net/",
18 | GraphEndpoint = "https://graph.windows.net/",
19 | StorageEndpointSuffix = "core.windows.net",
20 | KeyVaultSuffix = "vault.azure.net"
21 | };
22 | AzureChinaCloud = new AzureEnvironment()
23 | {
24 | Name = "China Cloud",
25 | AuthenticationEndpoint = "https://login.chinacloudapi.cn/",
26 | ResourceManagerEndpoint = "https://management.chinacloudapi.cn/",
27 | ManagementEndpoint = "https://management.core.chinacloudapi.cn/",
28 | GraphEndpoint = "https://graph.chinacloudapi.cn/",
29 | StorageEndpointSuffix = "core.chinacloudapi.cn",
30 | KeyVaultSuffix = "vault.azure.cn"
31 | };
32 | AzureUSGovernment = new AzureEnvironment()
33 | {
34 | Name = "US Government",
35 | AuthenticationEndpoint = "https://login.microsoftonline.us/",
36 | ResourceManagerEndpoint = "https://management.usgovcloudapi.net/",
37 | ManagementEndpoint = "https://management.core.usgovcloudapi.net",
38 | GraphEndpoint = "https://graph.windows.net/",
39 | StorageEndpointSuffix = "core.usgovcloudapi.net",
40 | KeyVaultSuffix = "vault.usgovcloudapi.net"
41 | };
42 | AzureGermanCloud = new AzureEnvironment()
43 | {
44 | Name = "German Cloud",
45 | AuthenticationEndpoint = "https://login.microsoftonline.de/",
46 | ResourceManagerEndpoint = "https://management.microsoftazure.de/",
47 | ManagementEndpoint = "https://management.core.cloudapi.de",
48 | GraphEndpoint = "https://graph.cloudapi.de/",
49 | StorageEndpointSuffix = "core.cloudapi.de",
50 | KeyVaultSuffix = "vault.microsoftazure.de"
51 | };
52 |
53 | Environments = new Dictionary
54 | {
55 | [AzureGlobalCloud.Name] = AzureGlobalCloud,
56 | [AzureChinaCloud.Name] = AzureChinaCloud,
57 | [AzureUSGovernment.Name] = AzureUSGovernment,
58 | [AzureGermanCloud.Name] = AzureGermanCloud,
59 | };
60 | }
61 |
62 | public static AzureEnvironment AzureGlobalCloud
63 | {
64 | get; private set;
65 | }
66 |
67 | public static AzureEnvironment AzureChinaCloud
68 | {
69 | get; private set;
70 | }
71 |
72 | public static AzureEnvironment AzureUSGovernment
73 | {
74 | get; private set;
75 | }
76 |
77 | public static AzureEnvironment AzureGermanCloud
78 | {
79 | get; private set;
80 | }
81 |
82 | public static IEnumerable KnownEnvironments
83 | {
84 | get
85 | {
86 | yield return AzureGlobalCloud;
87 | yield return AzureChinaCloud;
88 | yield return AzureUSGovernment;
89 | yield return AzureGermanCloud;
90 | }
91 | }
92 |
93 | public static Dictionary Environments
94 | {
95 | get; private set;
96 | }
97 |
98 | ///
99 | /// Name for the cloud environment
100 | ///
101 | public string Name { get; set; }
102 |
103 | ///
104 | /// Azure active directory service endpoint to get OAuth token to access ARM resource
105 | /// management endpoint .
106 | ///
107 | public string AuthenticationEndpoint { get; set; }
108 |
109 | ///
110 | /// Azure ARM resource management endpoint.
111 | ///
112 | public string ResourceManagerEndpoint { get; set; }
113 |
114 | ///
115 | /// Active Directory graph endpoint.
116 | ///
117 | public string GraphEndpoint { get; set; }
118 |
119 | ///
120 | /// Base URL for calls to service management (aka RDFE) and authentications to Active Directory.
121 | ///
122 | public string ManagementEndpoint { get; set; }
123 |
124 | ///
125 | /// The storage service url suffix.
126 | ///
127 | public string StorageEndpointSuffix { get; set; }
128 |
129 | ///
130 | /// The Key Vault service url suffix.
131 | ///
132 | public string KeyVaultSuffix { get; set; }
133 |
134 | ///
135 | /// Parse cloud environment name based on
136 | ///
137 | /// Cloud environment name
138 | /// An AzureEnvironment, or null if no matching environment found
139 | public static AzureEnvironment FromName(string name)
140 | => KnownEnvironments.FirstOrDefault(env => string.Equals(env.Name, name, StringComparison.OrdinalIgnoreCase));
141 | }
142 | }
--------------------------------------------------------------------------------
/Madd0.AzureStorageDriver/Model/CloudTable.cs:
--------------------------------------------------------------------------------
1 | //-----------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2012 Mauricio DIAZ ORLICH.
4 | // Code licensed under the MIT X11 license.
5 | //
6 | // Mauricio DIAZ ORLICH
7 | //-----------------------------------------------------------------------
8 |
9 | namespace Madd0.AzureStorageDriver
10 | {
11 | using System.Collections.Generic;
12 |
13 | ///
14 | /// Holds information about a table from Azure storage.
15 | ///
16 | public class CloudTable
17 | {
18 | ///
19 | /// Gets or sets the name of the table.
20 | ///
21 | public string Name
22 | {
23 | get;
24 | set;
25 | }
26 |
27 | ///
28 | /// Gets or sets the table's properties.
29 | ///
30 | public IEnumerable Columns
31 | {
32 | get;
33 | set;
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Madd0.AzureStorageDriver/Model/GenericEntity.cs:
--------------------------------------------------------------------------------
1 | //-----------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2012 Mauricio DIAZ ORLICH.
4 | // Code licensed under the MIT X11 license.
5 | //
6 | // Mauricio DIAZ ORLICH
7 | //-----------------------------------------------------------------------
8 |
9 | namespace Madd0.AzureStorageDriver
10 | {
11 | #if NETCORE
12 | using Microsoft.Azure.Cosmos.Table;
13 | #else
14 | using Microsoft.Azure.CosmosDB.Table;
15 | #endif
16 | using System.Collections.Generic;
17 |
18 | ///
19 | /// Represents a generic entity from table storage.
20 | ///
21 | ///
22 | /// This class extends , which gives it the
23 | /// , and properties,
24 | /// but all other properties that are obtained from table storage are simply stored in its
25 | /// dictionary as string values, where the property name is the property in
26 | /// the dictionary.
27 | ///
28 | public class GenericEntity : TableEntity
29 | {
30 |
31 | ///
32 | /// Gets or sets the table name.
33 | ///
34 | /// The table name.
35 | public string TableName
36 | {
37 | get;
38 | set;
39 | }
40 |
41 | ///
42 | /// Gets the list of properties of a table entity (except for PartitionKey, RowKey and
43 | /// Timestamp) and their string values.
44 | ///
45 | public Dictionary Properties { get; } = new Dictionary();
46 |
47 | ///
48 | /// Gets or sets the with the specified property.
49 | ///
50 | /// The name of the property.
51 | public string this[string property]
52 | {
53 | get
54 | {
55 | return this.Properties[property];
56 | }
57 |
58 | set
59 | {
60 | this.Properties[property] = value;
61 | }
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/Madd0.AzureStorageDriver/Model/StorageAccountProperties.cs:
--------------------------------------------------------------------------------
1 | //-----------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2012 Mauricio DIAZ ORLICH.
4 | // Code licensed under the MIT X11 license.
5 | //
6 | // Mauricio DIAZ ORLICH
7 | //-----------------------------------------------------------------------
8 |
9 | namespace Madd0.AzureStorageDriver
10 | {
11 | using System.Collections.Generic;
12 | using System.Linq;
13 | using System.Xml.Linq;
14 | using LINQPad.Extensibility.DataContext;
15 | using Madd0.AzureStorageDriver.Properties;
16 | #if NETCORE
17 | using Microsoft.Azure.Cosmos.Table;
18 | #else
19 | using Microsoft.Azure.Storage;
20 | using Microsoft.Azure.Storage.Auth;
21 | #endif
22 |
23 | ///
24 | /// Wrapper to expose typed properties over ConnectionInfo.DriverData.
25 | ///
26 | public class StorageAccountProperties
27 | {
28 | private readonly IConnectionInfo _connectionInfo;
29 | private readonly XElement _driverData;
30 |
31 | ///
32 | /// Initializes a new instance of the class.
33 | ///
34 | /// The connection info.
35 | public StorageAccountProperties(IConnectionInfo connectionInfo)
36 | {
37 | this._connectionInfo = connectionInfo;
38 | this._driverData = connectionInfo.DriverData;
39 | }
40 |
41 | ///
42 | /// Gets or sets a value indicating whether this connection should be remembered.
43 | ///
44 | /// true if this connection should be remembered; otherwise, false.
45 | public bool Persist
46 | {
47 | get { return this._connectionInfo.Persist; }
48 | set { this._connectionInfo.Persist = value; }
49 | }
50 |
51 | ///
52 | /// Gets the display name of the connection.
53 | ///
54 | public string DisplayName
55 | {
56 | get
57 | {
58 | if (this.UseLocalStorage)
59 | {
60 | return Resources.LocalStorageDisplayName;
61 | }
62 | else
63 | {
64 | return this.AccountName;
65 | }
66 | }
67 | }
68 |
69 | ///
70 | /// Gets or sets a value indicating whether local storage is being used.
71 | ///
72 | /// true if local storage is used; otherwise, false.
73 | public bool UseLocalStorage
74 | {
75 | get
76 | {
77 | return (bool?)this._driverData.Element("UseLocalStorage") ?? false;
78 | }
79 |
80 | set
81 | {
82 | this._driverData.SetElementValue("UseLocalStorage", value);
83 |
84 | if (value)
85 | {
86 | this.ClearAccountNameAndKey();
87 | }
88 | }
89 | }
90 |
91 | ///
92 | /// Gets or sets a value indicating whether to use HTTPS.
93 | ///
94 | /// true if HTTPS is used; otherwise, false.
95 | public bool UseHttps
96 | {
97 | get
98 | {
99 | return (bool?)this._driverData.Element("UseHttps") ?? false;
100 | }
101 |
102 | set
103 | {
104 | this._driverData.SetElementValue("UseHttps", value);
105 | }
106 | }
107 |
108 | ///
109 | /// Gets or sets the name of the storage account.
110 | ///
111 | public string AccountName
112 | {
113 | get { return (string)this._driverData.Element("AccountName") ?? string.Empty; }
114 | set { this._driverData.SetElementValue("AccountName", value); }
115 | }
116 |
117 | ///
118 | /// Gets or sets the key for the storage account.
119 | ///
120 | public string AccountKey
121 | {
122 | get
123 | {
124 | var encryptedKey = (string)this._driverData.Element("AccountKey") ?? string.Empty;
125 | return this._connectionInfo.Decrypt(encryptedKey);
126 | }
127 |
128 | set
129 | {
130 | var encryptedValue = this._connectionInfo.Encrypt(value);
131 | this._driverData.SetElementValue("AccountKey", encryptedValue);
132 | }
133 | }
134 |
135 | ///
136 | /// Gets or sets the number of rows to sample to determine a table's schema.
137 | ///
138 | public int NumberOfRows
139 | {
140 | get { return (int?)this._driverData.Element("NumberOfRows") ?? 1; }
141 | set { this._driverData.SetElementValue("NumberOfRows", value); }
142 | }
143 |
144 | ///
145 | /// Returns the maximum number of parallel model loading
146 | /// operations can occur when loading schema for the azure table storage tables
147 | ///
148 | public int ModelLoadMaxParallelism
149 | {
150 | get
151 | {
152 | return (int?)this._driverData.Element("ModelLoadMaxParallelism") ??
153 | (System.Environment.ProcessorCount * 2);
154 | }
155 | set
156 | {
157 | this._driverData.SetElementValue("ModelLoadMaxParallelism", value);
158 | }
159 | }
160 |
161 | public IEnumerable Environments => AzureEnvironment.KnownEnvironments;
162 |
163 | public AzureEnvironment AzureEnvironment
164 | {
165 | get
166 | {
167 | var selected = (string)_driverData.Element("AzureEnvironment");
168 |
169 | if (!string.IsNullOrEmpty(selected))
170 | {
171 | return AzureEnvironment.Environments[selected];
172 | }
173 | else
174 | {
175 | return AzureEnvironment.KnownEnvironments.First();
176 | }
177 | }
178 | set
179 | {
180 | this._driverData.SetElementValue("AzureEnvironment", value.Name);
181 | }
182 | }
183 |
184 | ///
185 | /// Gets a instace for the current connection.
186 | ///
187 | /// A instace configured with the credentials
188 | /// of the current connection.
189 | public CloudStorageAccount GetStorageAccount()
190 | {
191 | if (this.UseLocalStorage)
192 | {
193 | return CloudStorageAccount.DevelopmentStorageAccount;
194 | }
195 | else
196 | {
197 | return new CloudStorageAccount(
198 | new StorageCredentials(this.AccountName, this.AccountKey),
199 | this.AzureEnvironment.StorageEndpointSuffix,
200 | this.UseHttps);
201 | }
202 | }
203 |
204 | ///
205 | /// Clears the account name and key.
206 | ///
207 | /// This method is called when local storage is used.
208 | private void ClearAccountNameAndKey()
209 | {
210 | var accountName = this._driverData.Element("AccountName");
211 | var accountKey = this._driverData.Element("AccountKey");
212 |
213 | if (null != accountName)
214 | {
215 | accountName.Remove();
216 | }
217 |
218 | if (null != accountKey)
219 | {
220 | accountKey.Remove();
221 | }
222 | }
223 | }
224 | }
--------------------------------------------------------------------------------
/Madd0.AzureStorageDriver/Model/TableColumn.cs:
--------------------------------------------------------------------------------
1 | //-----------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2012 Mauricio DIAZ ORLICH.
4 | // Code licensed under the MIT X11 license.
5 | //
6 | // Mauricio DIAZ ORLICH
7 | //-----------------------------------------------------------------------
8 |
9 | namespace Madd0.AzureStorageDriver
10 | {
11 | ///
12 | /// Holds information about a column of a table in Azure storage.
13 | ///
14 | public class TableColumn
15 | {
16 | ///
17 | /// Gets or sets the name of the property.
18 | ///
19 | public string Name
20 | {
21 | get;
22 | set;
23 | }
24 |
25 | ///
26 | /// Gets or sets the type name of the property.
27 | ///
28 | public string TypeName
29 | {
30 | get;
31 | set;
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Madd0.AzureStorageDriver/Properties/Exceptions.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.239
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 Madd0.AzureStorageDriver.Properties {
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 Exceptions {
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 Exceptions() {
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("Madd0.AzureStorageDriver.Properties.Exceptions", typeof(Exceptions).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 Cannot compile typed context: {0} (line {1}).
65 | ///
66 | internal static string CannotCompileCode {
67 | get {
68 | return ResourceManager.GetString("CannotCompileCode", resourceCulture);
69 | }
70 | }
71 |
72 | ///
73 | /// Looks up a localized string similar to Deserialized type '{0}' is not supported..
74 | ///
75 | internal static string TypeNotSupported {
76 | get {
77 | return ResourceManager.GetString("TypeNotSupported", resourceCulture);
78 | }
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/Madd0.AzureStorageDriver/Properties/Exceptions.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 | Cannot compile typed context: {0} (line {1})
122 |
123 |
124 | Deserialized type '{0}' is not supported.
125 |
126 |
--------------------------------------------------------------------------------
/Madd0.AzureStorageDriver/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.239
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 Madd0.AzureStorageDriver.Properties {
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 Resources {
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 Resources() {
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("Madd0.AzureStorageDriver.Properties.Resources", typeof(Resources).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 AzureTableStorage.
65 | ///
66 | internal static string AssemblyTitle {
67 | get {
68 | return ResourceManager.GetString("AssemblyTitle", resourceCulture);
69 | }
70 | }
71 |
72 | ///
73 | /// Looks up a localized string similar to 0.1.0.0.
74 | ///
75 | internal static string AssemblyVersion {
76 | get {
77 | return ResourceManager.GetString("AssemblyVersion", resourceCulture);
78 | }
79 | }
80 |
81 | ///
82 | /// Looks up a localized string similar to Mauricio Diaz Orlich.
83 | ///
84 | internal static string AuthorName {
85 | get {
86 | return ResourceManager.GetString("AuthorName", resourceCulture);
87 | }
88 | }
89 |
90 | ///
91 | /// Looks up a localized string similar to Azure Table Storage Driver.
92 | ///
93 | internal static string DriverName {
94 | get {
95 | return ResourceManager.GetString("DriverName", resourceCulture);
96 | }
97 | }
98 |
99 | ///
100 | /// Looks up a localized string similar to (Development).
101 | ///
102 | internal static string LocalStorageDisplayName {
103 | get {
104 | return ResourceManager.GetString("LocalStorageDisplayName", resourceCulture);
105 | }
106 | }
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/Madd0.AzureStorageDriver/Properties/Resources.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 | Mauricio Diaz Orlich
122 |
123 |
124 | Azure Table Storage Driver
125 |
126 |
127 | (Development)
128 |
129 |
--------------------------------------------------------------------------------
/Madd0.AzureStorageDriver/SchemaBuilder.cs:
--------------------------------------------------------------------------------
1 | //-----------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2012 Mauricio DIAZ ORLICH.
4 | // Code licensed under the MIT X11 license.
5 | //
6 | // Mauricio DIAZ ORLICH
7 | //-----------------------------------------------------------------------
8 | namespace Madd0.AzureStorageDriver
9 | {
10 | #if NETCORE
11 | using Microsoft.Azure.Cosmos.Table;
12 | #else
13 | using Microsoft.Azure.CosmosDB.Table;
14 | #endif
15 |
16 | using System;
17 | using System.Collections.Generic;
18 | using System.IO;
19 | using System.Linq;
20 | using System.Net;
21 | using System.Reflection;
22 | using System.Threading.Tasks;
23 | using LINQPad.Extensibility.DataContext;
24 | using Madd0.AzureStorageDriver.Properties;
25 |
26 |
27 | ///
28 | /// Provides the methods necessary to determining the storage account's schema and to building
29 | /// the typed data context .
30 | ///
31 | internal static class SchemaBuilder
32 | {
33 | // Names of columns that should be marked as table keys.
34 | private static readonly List KeyColumns = new List { "PartitionKey", "RowKey" };
35 |
36 | ///
37 | /// Gets the schema and builds the assembly.
38 | ///
39 | /// The current configuration.
40 | /// The instace of the assembly being created.
41 | /// The namespace to be used in the generated code.
42 | /// Name of the type of the typed data context.
43 | /// A list of instaces that describes the current schema.
44 | public static List GetSchemaAndBuildAssembly(StorageAccountProperties properties, AssemblyName name, string @namepace, string typeName)
45 | {
46 | // Get the model from Azure storage
47 | var model = GetModel(properties);
48 |
49 | // Generate C# code
50 | var code = GenerateCode(typeName, @namepace, model);
51 |
52 | // And compile the code into the assembly
53 | BuildAssembly(name, code);
54 |
55 | // Generate the schema for LINQPad
56 | List schema = GetSchema(model);
57 |
58 | return schema;
59 | }
60 |
61 | ///
62 | /// Build a model of the current Azure storage account. This model will be used to generate
63 | /// the typed code as well as the schema needed by LINQPad.
64 | ///
65 | /// The current configuration.
66 | /// A list of instances that describe the current Azure
67 | /// storage model.
68 | private static IEnumerable GetModel(StorageAccountProperties properties)
69 | {
70 | // make sure that we can make at least ModelLoadMaxParallelism concurrent
71 | // cals to azure table storage
72 | ServicePointManager.DefaultConnectionLimit = properties.ModelLoadMaxParallelism;
73 |
74 | var tableClient = properties.GetStorageAccount().CreateCloudTableClient();
75 |
76 | // First get a list of all tables
77 | var model = (from tableName in tableClient.ListTables()
78 | select new CloudTable
79 | {
80 | Name = tableName.Name
81 | }).ToList();
82 |
83 | var options = new ParallelOptions()
84 | {
85 | MaxDegreeOfParallelism = properties.ModelLoadMaxParallelism
86 | };
87 |
88 | Parallel.ForEach(model, options, table =>
89 | {
90 | var threadTableClient = properties.GetStorageAccount().CreateCloudTableClient();
91 |
92 | var tableColumns = threadTableClient.GetTableReference(table.Name).ExecuteQuery(new TableQuery().Take(properties.NumberOfRows))
93 | .SelectMany(row => row.Properties)
94 | .GroupBy(column => column.Key)
95 | .Select(grp => new TableColumn
96 | {
97 | Name = grp.Key,
98 | TypeName = GetType(grp.First().Value.PropertyType)
99 | });
100 |
101 | var baseColumns = new List
102 | {
103 | new TableColumn { Name = "PartitionKey", TypeName = GetType(EdmType.String) },
104 | new TableColumn { Name = "RowKey", TypeName = GetType(EdmType.String) },
105 | new TableColumn { Name = "Timestamp", TypeName = GetType(EdmType.DateTime) },
106 | new TableColumn { Name = "ETag", TypeName = GetType(EdmType.String) }
107 | };
108 |
109 | table.Columns = tableColumns.Concat(baseColumns).ToArray();
110 | });
111 |
112 | return model;
113 | }
114 |
115 | ///
116 | /// Generates the code to build the typed data context.
117 | ///
118 | /// Name of the type.
119 | /// The namespace.
120 | /// The model.
121 | /// The code to be compiled as a string.
122 | private static string GenerateCode(string typeName, string @namespace, IEnumerable model)
123 | {
124 | // We use a T4-generated class as the template
125 | var codeGenerator = new DataContextTemplate
126 | {
127 | Namespace = @namespace,
128 | TypeName = typeName,
129 | Tables = model
130 | };
131 |
132 | // As a workaround for compiling issues when referencing the driver DLL itself to
133 | // access the base ExtendedTableQuery class, the code will be used instead in the
134 | // dynamic assembly.
135 | var baseClass = ReadEmbeddedBaseClassCode();
136 |
137 | var sourceCode = baseClass + codeGenerator.TransformText();
138 | LINQPad.Util.Break();
139 |
140 | return sourceCode;
141 | }
142 |
143 | private static string ReadEmbeddedBaseClassCode()
144 | {
145 | var assembly = Assembly.GetExecutingAssembly();
146 | var resourceName = "Madd0.AzureStorageDriver.ExtendedTableQuery.cs";
147 |
148 | using var reader = new StreamReader(assembly.GetManifestResourceStream(resourceName));
149 |
150 | return reader.ReadToEnd();
151 | }
152 |
153 | ///
154 | /// Builds the assembly described by the .
155 | ///
156 | /// The instace of the assembly being created.
157 | /// The code of the typed data context.
158 | private static void BuildAssembly(AssemblyName name, string code)
159 | {
160 | ICompiler compiler;
161 |
162 | var dependencies = new List
163 | {
164 | typeof(TableQuery).Assembly.Location
165 | };
166 | #if NETCORE
167 | compiler = new RoslynCompiler();
168 | #else
169 | compiler = new CodeDomCompiler();
170 | dependencies.Add("System.dll");
171 | dependencies.Add("System.Core.dll");
172 | dependencies.Add("System.Xml.dll");
173 | dependencies.Add(typeof(Microsoft.Azure.Storage.OperationContext).Assembly.Location);
174 | #endif
175 | compiler.Compile(code, name, dependencies);
176 | }
177 |
178 | ///
179 | /// Transforms the model based on instances into a schema based on
180 | /// instances for LINQPad.
181 | ///
182 | /// The model.
183 | /// A schema for LINQPad.
184 | private static List GetSchema(IEnumerable model)
185 | {
186 | return (from table in model
187 | select new ExplorerItem(table.Name, ExplorerItemKind.QueryableObject, ExplorerIcon.Table)
188 | {
189 | Children = (from column in table.Columns
190 | select new ExplorerItem(column.Name + " (" + column.TypeName + ")", ExplorerItemKind.Property, ExplorerIcon.Column)
191 | {
192 | Icon = KeyColumns.Contains(column.Name) ? ExplorerIcon.Key : ExplorerIcon.Column,
193 | DragText = column.Name
194 | }).ToList(),
195 | DragText = table.Name,
196 | IsEnumerable = true
197 | }).ToList();
198 | }
199 |
200 | ///
201 | /// Gets the C# type equivalent of an entity data model (Edm) type.
202 | ///
203 | /// The Edm type.
204 | /// The C# type.
205 | private static string GetType(EdmType type)
206 | {
207 | return type switch
208 | {
209 | EdmType.Binary => "byte[]",
210 |
211 | EdmType.Boolean => "bool?",
212 |
213 | EdmType.DateTime => "DateTime?",
214 |
215 | EdmType.Double => "double?",
216 |
217 | EdmType.Guid => "Guid?",
218 |
219 | EdmType.Int32 => "int?",
220 |
221 | EdmType.Int64 => "long?",
222 |
223 | EdmType.String => "string",
224 |
225 | _ => throw new NotSupportedException(string.Format(Exceptions.TypeNotSupported, type)),
226 | };
227 | }
228 | }
229 | }
--------------------------------------------------------------------------------
/Madd0.AzureStorageDriver/UserQuery/ExtendedTableQuery.cs:
--------------------------------------------------------------------------------
1 | //-----------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2014 Mauricio DIAZ ORLICH.
4 | // Code licensed under the MIT X11 license.
5 | //
6 | // Mauricio DIAZ ORLICH
7 | //-----------------------------------------------------------------------
8 |
9 | namespace Madd0.UserQuery
10 | {
11 | #if NETCORE
12 | using Microsoft.Azure.Cosmos.Table;
13 | #else
14 | using Microsoft.Azure.CosmosDB.Table;
15 | using Microsoft.Azure.Storage;
16 | #endif
17 | using System.Collections;
18 | using System.Collections.Generic;
19 | using System.IO;
20 | using System.Linq;
21 |
22 | public class ExtendedTableQuery
23 | {
24 |
25 | public TextWriter QueryWriter
26 | {
27 | get;
28 | set;
29 | }
30 |
31 | }
32 | public class ExtendedTableQuery : ExtendedTableQuery, IQueryable
33 | where TElement : ITableEntity, new()
34 | {
35 | private readonly TableQuery _query;
36 |
37 | public ExtendedTableQuery(CloudTable table)
38 | {
39 | this.CloudTable = table;
40 | _query = table.CreateQuery();
41 | }
42 |
43 | #if !NETCORE
44 | public ICancellableAsyncResult BeginExecuteSegmented(TableContinuationToken currentToken, TableRequestOptions requestOptions, OperationContext operationContext, System.AsyncCallback callback, object state)
45 | {
46 | return _query.BeginExecuteSegmented(currentToken, requestOptions, operationContext, callback, state);
47 | }
48 |
49 | public ICancellableAsyncResult BeginExecuteSegmented(TableContinuationToken currentToken, System.AsyncCallback callback, object state)
50 | {
51 | return _query.BeginExecuteSegmented(currentToken, callback, state);
52 | }
53 |
54 | public TableQuerySegment EndExecuteSegmented(System.IAsyncResult asyncResult)
55 | {
56 | return _query.EndExecuteSegmented(asyncResult);
57 | }
58 | #endif
59 |
60 | public System.Collections.Generic.IEnumerable Execute(TableRequestOptions requestOptions = null, OperationContext operationContext = null)
61 | {
62 | return _query.Execute(requestOptions, operationContext);
63 | }
64 |
65 | public TableQuerySegment ExecuteSegmented(TableContinuationToken continuationToken, TableRequestOptions requestOptions = null, OperationContext operationContext = null)
66 | {
67 | return _query.ExecuteSegmented(continuationToken, requestOptions, operationContext);
68 | }
69 |
70 | public System.Threading.Tasks.Task> ExecuteSegmentedAsync(TableContinuationToken currentToken, TableRequestOptions requestOptions, OperationContext operationContext, System.Threading.CancellationToken cancellationToken)
71 | {
72 | return _query.ExecuteSegmentedAsync(currentToken, requestOptions, operationContext, cancellationToken);
73 | }
74 |
75 | public System.Threading.Tasks.Task> ExecuteSegmentedAsync(TableContinuationToken currentToken, TableRequestOptions requestOptions, OperationContext operationContext)
76 | {
77 | return _query.ExecuteSegmentedAsync(currentToken, requestOptions, operationContext);
78 | }
79 |
80 | public System.Threading.Tasks.Task> ExecuteSegmentedAsync(TableContinuationToken currentToken, System.Threading.CancellationToken cancellationToken)
81 | {
82 | return _query.ExecuteSegmentedAsync(currentToken, cancellationToken);
83 | }
84 |
85 | public System.Threading.Tasks.Task> ExecuteSegmentedAsync(TableContinuationToken currentToken)
86 | {
87 | return _query.ExecuteSegmentedAsync(currentToken);
88 | }
89 |
90 | public System.Collections.Generic.IEnumerator GetEnumerator()
91 | {
92 | return _query.GetEnumerator();
93 | }
94 |
95 | System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
96 | {
97 | return this.GetEnumerator();
98 | }
99 |
100 | public TableQuery Select(System.Collections.Generic.IList columns)
101 | {
102 | return _query.Select(columns);
103 | }
104 |
105 | public TableQuery Take(int? take)
106 | {
107 | return _query.Take(take);
108 | }
109 |
110 | public TableQuery Where(string filter)
111 | {
112 | return _query.Where(filter);
113 | }
114 |
115 | public System.Type ElementType
116 | {
117 | get
118 | {
119 | return _query.ElementType;
120 | }
121 | }
122 |
123 | public System.Linq.Expressions.Expression Expression
124 | {
125 | get
126 | {
127 | return _query.Expression;
128 | }
129 | }
130 |
131 | public string FilterString
132 | {
133 | set
134 | {
135 | _query.FilterString = value;
136 | }
137 | get
138 | {
139 | return _query.FilterString;
140 | }
141 | }
142 |
143 | public System.Linq.IQueryProvider Provider
144 | {
145 | get
146 | {
147 | return _query.Provider;
148 | }
149 | }
150 |
151 | public System.Collections.Generic.IList SelectColumns
152 | {
153 | set
154 | {
155 | _query.SelectColumns = value;
156 | }
157 | get
158 | {
159 | return _query.SelectColumns;
160 | }
161 | }
162 |
163 | public int? TakeCount
164 | {
165 | set
166 | {
167 | _query.TakeCount = value;
168 | }
169 | get
170 | {
171 | return _query.TakeCount;
172 | }
173 | }
174 |
175 | public CloudTable CloudTable { get; private set; }
176 | }
177 | }
178 |
--------------------------------------------------------------------------------
/Madd0.AzureStorageDriver/header.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Madd0.AzureStorageDriver.dll
4 | https://github.com/madd0/AzureStorageDriver
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # README #
2 |
3 | This is a plug-in for [LINQPad](http://www.linqpad.net) that enables the
4 | execution of queries against [Azure Table Storage](https://docs.microsoft.com/en-us/azure/cosmos-db/table-storage-overview).
5 |
6 | It allows you to add storage accounts as connections in LINQPad.
7 | It will list all tables for each account and all columns in each table.
8 | Since Azure tables can have mixed schemas, a property was added in version 1.1.0
9 | allowing users to specify the number of rows that should be scanned to determine
10 | the schema of each table. For the same reason, any value types are made
11 | `Nullable<>` since it cannot be guaranteed that they will have a value
12 | for a given row.
13 |
14 | [](https://www.nuget.org/packages/Madd0.AzureStorageDriver/) [](https://dev.azure.com/madd0/AzureStorageDriver/_build/latest?definitionId=4&branchName=master)
15 |
16 | ## Issues and Feature requests ##
17 |
18 | Issues and feature requests can be made in the projects
19 | [issues page on GitHub](https://github.com/madd0/AzureStorageDriver/issues).
20 |
21 | ## Versions ##
22 |
23 | ### v2.1.2 - 2022-11-13 ###
24 |
25 | * Updated dependency versions:
26 | * LINQPad.Reference: 1.1.0 -> 1.3.0
27 | * SonarAnalyzer.CSharp: 8.0.0.9566 -> 8.48.0.56517
28 | * Microsoft.CodeAnalysis.CSharp: 3.3.1 -> 3.11.0
29 |
30 | * Added explicit reference to Newtonsoft.Json to work around issue [#22][11]
31 | ### v2.1.1 - 2020-02-04 ###
32 |
33 | * Workaround for problem described in [#20][10]
34 | * The .NET Core 3.1 driver was getting .NET Core 3.0 references, which prevented it from compiling the generated code because
35 | the driver itself was a reference and therefore needed 3.1 references.
36 | * As a workaround, the driver is no longer a required reference for the generated code, which is compatible with either
37 | .NET Core 3.0 or 3.1, so no matter what runtime LinqPad provides, the code should compile.
38 |
39 | ### v2.1.0 - 2020-01-05 ###
40 |
41 | Happy new year! After last month's update, I decided to work on some really
42 | old pending PRs, do some cleanup and tackle [#19][7] which came in on the first day of the year.
43 |
44 | * Integrate PR [#8: add support for china azure(code name:mooncake)][8]
45 | * Adds support for China, US Government and German "clouds."
46 | * Found by expanding the _Advanced_ section in the connection properties dialog.
47 | * Integrate PR [#12: Enable parallel schema loading ][9]
48 | * Speeds up loading of storage accounts with multiple tables.
49 | * Max number of parallel queries can be set in the _Advanced_ section in the connection properties dialog.
50 | * Target .NET Core 3.1
51 | * The Nuget package now includes .NET 4.6, .NET Core 3.0 _and_ .NET Core 3.1 versions.
52 | * The .NET Core 3.1 version of the DLL should prevent issues such as described in [#19: When .NET Core 3.1 installed, "Cannot compile typed context" error][7]
53 |
54 | ### v2.0.0 - 2019-12-01 ###
55 |
56 | It took a while for a new version to come out, but with [LINQPad 6][3]
57 | and big changes in the Azure SDK libraries, I thought it was time.
58 | And, although functionally not much has changed, I decided that a new
59 | distribution channel and total change in the underlying SDK,
60 | deserved a new major version.
61 |
62 | * **New:** Available as [a Nuget package][4] for LINQPad 6.
63 | * Switch to _Azure Cosmos DB Table API_
64 | * LINQPad 6 plugin uses [Microsoft.Azure.Cosmos.Table 1.0.5][5]
65 | * LINQPad 5 plugin uses [Microsoft.Azure.CosmosDB.Table 2.1.2][6]
66 |
67 |
68 | _Note: the Azure Storage SDK used by the LINQPad 5 version is in maintenance mode
69 | and it will be deprecated soon according to Microsoft. However, since LINQPad 5
70 | plugins target .NET Framework 4.6, the switch to the package used by the LINQPad 6
71 | plugin is not possible._
72 |
73 | ### v1.1.0 - 2014-08-20 ###
74 |
75 | * Uses latest version of [Azure Storage Client Library](https://github.com/Azure/azure-storage-net/) (4.2.0)
76 | * Provides a solution to issue [#1][2] by adding a configuration parameter that allows users to specify
77 | the number of rows to be scanned to determine the schema of a table (100 by default).
78 |
79 | ### v1.0.1 - 2013-08-15 ###
80 |
81 | Corrects issue [#4][1].
82 |
83 | ### v1.0.0-beta - 2010-01-08 ###
84 |
85 | This is the first public release. Needs real-world testing.
86 |
87 | [1]: https://github.com/madd0/AzureStorageDriver/issues/4
88 | [2]: https://github.com/madd0/AzureStorageDriver/issues/1
89 | [3]: https://www.linqpad.net/LINQPad6.aspx
90 | [4]: https://www.nuget.org/packages/Madd0.AzureStorageDriver/
91 | [5]: https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Table
92 | [6]: https://www.nuget.org/packages/Microsoft.Azure.CosmosDB.Table
93 | [7]: https://github.com/madd0/AzureStorageDriver/issues/19
94 | [8]: https://github.com/madd0/AzureStorageDriver/pull/8
95 | [9]: https://github.com/madd0/AzureStorageDriver/pull/12
96 | [10]: https://github.com/madd0/AzureStorageDriver/issues/20
97 | [11]: https://github.com/madd0/AzureStorageDriver/issues/22
98 |
--------------------------------------------------------------------------------
/Settings.XamlStyler:
--------------------------------------------------------------------------------
1 | {
2 | "KeepFirstAttributeOnSameLine": true,
3 | "ThicknessSeparator": 1
4 | }
5 |
--------------------------------------------------------------------------------