· 9 years ago · Feb 02, 2017, 10:30 PM
1# Copyright (c) Microsoft Corporation. All rights reserved.
2
3$InitialDatabase = '0'
4
5$knownExceptions = @(
6 'System.Data.Entity.Migrations.Infrastructure.MigrationsException',
7 'System.Data.Entity.Migrations.Infrastructure.AutomaticMigrationsDisabledException',
8 'System.Data.Entity.Migrations.Infrastructure.AutomaticDataLossException',
9 'System.Data.Entity.Migrations.Infrastructure.MigrationsPendingException',
10 'System.Data.Entity.Migrations.ProjectTypeNotSupportedException'
11)
12
13<#
14.SYNOPSIS
15 Adds or updates an Entity Framework provider entry in the project config
16 file.
17
18.DESCRIPTION
19 Adds an entry into the 'entityFramework' section of the project config
20 file for the specified provider invariant name and provider type. If an
21 entry for the given invariant name already exists, then that entry is
22 updated with the given type name, unless the given type name already
23 matches, in which case no action is taken. The 'entityFramework'
24 section is added if it does not exist. The config file is automatically
25 saved if and only if a change was made.
26
27 This command is typically used only by Entity Framework provider NuGet
28 packages and is run from the 'install.ps1' script.
29
30.PARAMETER Project
31 The Visual Studio project to update. When running in the NuGet install.ps1
32 script the '$project' variable provided as part of that script should be
33 used.
34
35.PARAMETER InvariantName
36 The provider invariant name that uniquely identifies this provider. For
37 example, the Microsoft SQL Server provider is registered with the invariant
38 name 'System.Data.SqlClient'.
39
40.PARAMETER TypeName
41 The assembly-qualified type name of the provider-specific type that
42 inherits from 'System.Data.Entity.Core.Common.DbProviderServices'. For
43 example, for the Microsoft SQL Server provider, this type is
44 'System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer'.
45#>
46function Add-EFProvider
47{
48 param (
49 [parameter(Position = 0,
50 Mandatory = $true)]
51 $Project,
52 [parameter(Position = 1,
53 Mandatory = $true)]
54 [string] $InvariantName,
55 [parameter(Position = 2,
56 Mandatory = $true)]
57 [string] $TypeName
58 )
59
60 if (!(Check-Project $project))
61 {
62 return
63 }
64
65 $runner = New-EFConfigRunner $Project
66
67 try
68 {
69 Invoke-RunnerCommand $runner System.Data.Entity.ConnectionFactoryConfig.AddProviderCommand @( $InvariantName, $TypeName )
70 $error = Get-RunnerError $runner
71
72 if ($error)
73 {
74 if ($knownExceptions -notcontains $error.TypeName)
75 {
76 Write-Host $error.StackTrace
77 }
78 else
79 {
80 Write-Verbose $error.StackTrace
81 }
82
83 throw $error.Message
84 }
85 }
86 finally
87 {
88 Remove-Runner $runner
89 }
90}
91
92<#
93.SYNOPSIS
94 Adds or updates an Entity Framework default connection factory in the
95 project config file.
96
97.DESCRIPTION
98 Adds an entry into the 'entityFramework' section of the project config
99 file for the connection factory that Entity Framework will use by default
100 when creating new connections by convention. Any existing entry will be
101 overridden if it does not match. The 'entityFramework' section is added if
102 it does not exist. The config file is automatically saved if and only if
103 a change was made.
104
105 This command is typically used only by Entity Framework provider NuGet
106 packages and is run from the 'install.ps1' script.
107
108.PARAMETER Project
109 The Visual Studio project to update. When running in the NuGet install.ps1
110 script the '$project' variable provided as part of that script should be
111 used.
112
113.PARAMETER TypeName
114 The assembly-qualified type name of the connection factory type that
115 implements the 'System.Data.Entity.Infrastructure.IDbConnectionFactory'
116 interface. For example, for the Microsoft SQL Server Express provider
117 connection factory, this type is
118 'System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework'.
119
120.PARAMETER ConstructorArguments
121 An optional array of strings that will be passed as arguments to the
122 connection factory type constructor.
123#>
124function Add-EFDefaultConnectionFactory
125{
126 param (
127 [parameter(Position = 0,
128 Mandatory = $true)]
129 $Project,
130 [parameter(Position = 1,
131 Mandatory = $true)]
132 [string] $TypeName,
133 [string[]] $ConstructorArguments
134 )
135
136 if (!(Check-Project $project))
137 {
138 return
139 }
140
141 $runner = New-EFConfigRunner $Project
142
143 try
144 {
145 Invoke-RunnerCommand $runner System.Data.Entity.ConnectionFactoryConfig.AddDefaultConnectionFactoryCommand @( $TypeName, $ConstructorArguments )
146 $error = Get-RunnerError $runner
147
148 if ($error)
149 {
150 if ($knownExceptions -notcontains $error.TypeName)
151 {
152 Write-Host $error.StackTrace
153 }
154 else
155 {
156 Write-Verbose $error.StackTrace
157 }
158
159 throw $error.Message
160 }
161 }
162 finally
163 {
164 Remove-Runner $runner
165 }
166}
167
168<#
169.SYNOPSIS
170 Initializes the Entity Framework section in the project config file
171 and sets defaults.
172
173.DESCRIPTION
174 Creates the 'entityFramework' section of the project config file and sets
175 the default connection factory to use SQL Express if it is running on the
176 machine, or LocalDb otherwise. Note that installing a different provider
177 may change the default connection factory. The config file is
178 automatically saved if and only if a change was made.
179
180 In addition, any reference to 'System.Data.Entity.dll' in the project is
181 removed.
182
183 This command is typically used only by Entity Framework provider NuGet
184 packages and is run from the 'install.ps1' script.
185
186.PARAMETER Project
187 The Visual Studio project to update. When running in the NuGet install.ps1
188 script the '$project' variable provided as part of that script should be
189 used.
190#>
191function Initialize-EFConfiguration
192{
193 param (
194 [parameter(Position = 0,
195 Mandatory = $true)]
196 $Project
197 )
198
199 if (!(Check-Project $project))
200 {
201 return
202 }
203
204 $runner = New-EFConfigRunner $Project
205
206 try
207 {
208 Invoke-RunnerCommand $runner System.Data.Entity.ConnectionFactoryConfig.InitializeEntityFrameworkCommand
209 $error = Get-RunnerError $runner
210
211 if ($error)
212 {
213 if ($knownExceptions -notcontains $error.TypeName)
214 {
215 Write-Host $error.StackTrace
216 }
217 else
218 {
219 Write-Verbose $error.StackTrace
220 }
221
222 throw $error.Message
223 }
224 }
225 finally
226 {
227 Remove-Runner $runner
228 }
229}
230
231<#
232.SYNOPSIS
233 Enables Code First Migrations in a project.
234
235.DESCRIPTION
236 Enables Migrations by scaffolding a migrations configuration class in the project. If the
237 target database was created by an initializer, an initial migration will be created (unless
238 automatic migrations are enabled via the EnableAutomaticMigrations parameter).
239
240.PARAMETER ContextTypeName
241 Specifies the context to use. If omitted, migrations will attempt to locate a
242 single context type in the target project.
243
244.PARAMETER EnableAutomaticMigrations
245 Specifies whether automatic migrations will be enabled in the scaffolded migrations configuration.
246 If omitted, automatic migrations will be disabled.
247
248.PARAMETER MigrationsDirectory
249 Specifies the name of the directory that will contain migrations code files.
250 If omitted, the directory will be named "Migrations".
251
252.PARAMETER ProjectName
253 Specifies the project that the scaffolded migrations configuration class will
254 be added to. If omitted, the default project selected in package manager
255 console is used.
256
257.PARAMETER StartUpProjectName
258 Specifies the configuration file to use for named connection strings. If
259 omitted, the specified project's configuration file is used.
260
261.PARAMETER ContextProjectName
262 Specifies the project which contains the DbContext class to use. If omitted,
263 the context is assumed to be in the same project used for migrations.
264
265.PARAMETER ConnectionStringName
266 Specifies the name of a connection string to use from the application's
267 configuration file.
268
269.PARAMETER ConnectionString
270 Specifies the the connection string to use. If omitted, the context's
271 default connection will be used.
272
273.PARAMETER ConnectionProviderName
274 Specifies the provider invariant name of the connection string.
275
276.PARAMETER Force
277 Specifies that the migrations configuration be overwritten when running more
278 than once for a given project.
279
280.PARAMETER ContextAssemblyName
281 Specifies the name of the assembly which contains the DbContext class to use. Use this
282 parameter instead of ContextProjectName when the context is contained in a referenced
283 assembly rather than in a project of the solution.
284
285.PARAMETER AppDomainBaseDirectory
286 Specifies the directory to use for the app-domain that is used for running Migrations
287 code such that the app-domain is able to find all required assemblies. This is an
288 advanced option that should only be needed if the solution contains several projects
289 such that the assemblies needed for the context and configuration are not all
290 referenced from either the project containing the context or the project containing
291 the migrations.
292
293.EXAMPLE
294 Enable-Migrations
295 # Scaffold a migrations configuration in a project with only one context
296
297.EXAMPLE
298 Enable-Migrations -Auto
299 # Scaffold a migrations configuration with automatic migrations enabled for a project
300 # with only one context
301
302.EXAMPLE
303 Enable-Migrations -ContextTypeName MyContext -MigrationsDirectory DirectoryName
304 # Scaffold a migrations configuration for a project with multiple contexts
305 # This scaffolds a migrations configuration for MyContext and will put the configuration
306 # and subsequent configurations in a new directory called "DirectoryName"
307
308#>
309function Enable-Migrations
310{
311 [CmdletBinding(DefaultParameterSetName = 'ConnectionStringName')]
312 param (
313 [string] $ContextTypeName,
314 [alias('Auto')]
315 [switch] $EnableAutomaticMigrations,
316 [string] $MigrationsDirectory,
317 [string] $ProjectName,
318 [string] $StartUpProjectName,
319 [string] $ContextProjectName,
320 [parameter(ParameterSetName = 'ConnectionStringName')]
321 [string] $ConnectionStringName,
322 [parameter(ParameterSetName = 'ConnectionStringAndProviderName',
323 Mandatory = $true)]
324 [string] $ConnectionString,
325 [parameter(ParameterSetName = 'ConnectionStringAndProviderName',
326 Mandatory = $true)]
327 [string] $ConnectionProviderName,
328 [switch] $Force,
329 [string] $ContextAssemblyName,
330 [string] $AppDomainBaseDirectory
331 )
332
333 $runner = New-MigrationsRunner $ProjectName $StartUpProjectName $ContextProjectName $null $ConnectionStringName $ConnectionString $ConnectionProviderName $ContextAssemblyName $AppDomainBaseDirectory
334
335 try
336 {
337 Invoke-RunnerCommand $runner System.Data.Entity.Migrations.EnableMigrationsCommand @( $EnableAutomaticMigrations.IsPresent, $Force.IsPresent ) @{ 'ContextTypeName' = $ContextTypeName; 'MigrationsDirectory' = $MigrationsDirectory }
338 $error = Get-RunnerError $runner
339
340 if ($error)
341 {
342 if ($knownExceptions -notcontains $error.TypeName)
343 {
344 Write-Host $error.StackTrace
345 }
346 else
347 {
348 Write-Verbose $error.StackTrace
349 }
350
351 throw $error.Message
352 }
353
354 $(Get-VSComponentModel).GetService([NuGetConsole.IPowerConsoleWindow]).Show()
355 }
356 finally
357 {
358 Remove-Runner $runner
359 }
360}
361
362<#
363.SYNOPSIS
364 Scaffolds a migration script for any pending model changes.
365
366.DESCRIPTION
367 Scaffolds a new migration script and adds it to the project.
368
369.PARAMETER Name
370 Specifies the name of the custom script.
371
372.PARAMETER Force
373 Specifies that the migration user code be overwritten when re-scaffolding an
374 existing migration.
375
376.PARAMETER ProjectName
377 Specifies the project that contains the migration configuration type to be
378 used. If omitted, the default project selected in package manager console
379 is used.
380
381.PARAMETER StartUpProjectName
382 Specifies the configuration file to use for named connection strings. If
383 omitted, the specified project's configuration file is used.
384
385.PARAMETER ConfigurationTypeName
386 Specifies the migrations configuration to use. If omitted, migrations will
387 attempt to locate a single migrations configuration type in the target
388 project.
389
390.PARAMETER ConnectionStringName
391 Specifies the name of a connection string to use from the application's
392 configuration file.
393
394.PARAMETER ConnectionString
395 Specifies the the connection string to use. If omitted, the context's
396 default connection will be used.
397
398.PARAMETER ConnectionProviderName
399 Specifies the provider invariant name of the connection string.
400
401.PARAMETER IgnoreChanges
402 Scaffolds an empty migration ignoring any pending changes detected in the current model.
403 This can be used to create an initial, empty migration to enable Migrations for an existing
404 database. N.B. Doing this assumes that the target database schema is compatible with the
405 current model.
406
407.PARAMETER AppDomainBaseDirectory
408 Specifies the directory to use for the app-domain that is used for running Migrations
409 code such that the app-domain is able to find all required assemblies. This is an
410 advanced option that should only be needed if the solution contains several projects
411 such that the assemblies needed for the context and configuration are not all
412 referenced from either the project containing the context or the project containing
413 the migrations.
414
415.EXAMPLE
416 Add-Migration First
417 # Scaffold a new migration named "First"
418
419.EXAMPLE
420 Add-Migration First -IgnoreChanges
421 # Scaffold an empty migration ignoring any pending changes detected in the current model.
422 # This can be used to create an initial, empty migration to enable Migrations for an existing
423 # database. N.B. Doing this assumes that the target database schema is compatible with the
424 # current model.
425
426#>
427function Add-Migration
428{
429 [CmdletBinding(DefaultParameterSetName = 'ConnectionStringName')]
430 param (
431 [parameter(Position = 0,
432 Mandatory = $true)]
433 [string] $Name,
434 [switch] $Force,
435 [string] $ProjectName,
436 [string] $StartUpProjectName,
437 [string] $ConfigurationTypeName,
438 [parameter(ParameterSetName = 'ConnectionStringName')]
439 [string] $ConnectionStringName,
440 [parameter(ParameterSetName = 'ConnectionStringAndProviderName',
441 Mandatory = $true)]
442 [string] $ConnectionString,
443 [parameter(ParameterSetName = 'ConnectionStringAndProviderName',
444 Mandatory = $true)]
445 [string] $ConnectionProviderName,
446 [switch] $IgnoreChanges,
447 [string] $AppDomainBaseDirectory)
448
449 $runner = New-MigrationsRunner $ProjectName $StartUpProjectName $null $ConfigurationTypeName $ConnectionStringName $ConnectionString $ConnectionProviderName $null $AppDomainBaseDirectory
450
451 try
452 {
453 Invoke-RunnerCommand $runner System.Data.Entity.Migrations.AddMigrationCommand @( $Name, $Force.IsPresent, $IgnoreChanges.IsPresent )
454 $error = Get-RunnerError $runner
455
456 if ($error)
457 {
458 if ($knownExceptions -notcontains $error.TypeName)
459 {
460 Write-Host $error.StackTrace
461 }
462 else
463 {
464 Write-Verbose $error.StackTrace
465 }
466
467 throw $error.Message
468 }
469 $(Get-VSComponentModel).GetService([NuGetConsole.IPowerConsoleWindow]).Show()
470 }
471 finally
472 {
473 Remove-Runner $runner
474 }
475}
476
477<#
478.SYNOPSIS
479 Applies any pending migrations to the database.
480
481.DESCRIPTION
482 Updates the database to the current model by applying pending migrations.
483
484.PARAMETER SourceMigration
485 Only valid with -Script. Specifies the name of a particular migration to use
486 as the update's starting point. If omitted, the last applied migration in
487 the database will be used.
488
489.PARAMETER TargetMigration
490 Specifies the name of a particular migration to update the database to. If
491 omitted, the current model will be used.
492
493.PARAMETER Script
494 Generate a SQL script rather than executing the pending changes directly.
495
496.PARAMETER Force
497 Specifies that data loss is acceptable during automatic migration of the
498 database.
499
500.PARAMETER ProjectName
501 Specifies the project that contains the migration configuration type to be
502 used. If omitted, the default project selected in package manager console
503 is used.
504
505.PARAMETER StartUpProjectName
506 Specifies the configuration file to use for named connection strings. If
507 omitted, the specified project's configuration file is used.
508
509.PARAMETER ConfigurationTypeName
510 Specifies the migrations configuration to use. If omitted, migrations will
511 attempt to locate a single migrations configuration type in the target
512 project.
513
514.PARAMETER ConnectionStringName
515 Specifies the name of a connection string to use from the application's
516 configuration file.
517
518.PARAMETER ConnectionString
519 Specifies the the connection string to use. If omitted, the context's
520 default connection will be used.
521
522.PARAMETER ConnectionProviderName
523 Specifies the provider invariant name of the connection string.
524
525.PARAMETER AppDomainBaseDirectory
526 Specifies the directory to use for the app-domain that is used for running Migrations
527 code such that the app-domain is able to find all required assemblies. This is an
528 advanced option that should only be needed if the solution contains several projects
529 such that the assemblies needed for the context and configuration are not all
530 referenced from either the project containing the context or the project containing
531 the migrations.
532
533.EXAMPLE
534 Update-Database
535 # Update the database to the latest migration
536
537.EXAMPLE
538 Update-Database -TargetMigration Second
539 # Update database to a migration named "Second"
540 # This will apply migrations if the target hasn't been applied or roll back migrations
541 # if it has
542
543.EXAMPLE
544 Update-Database -Script
545 # Generate a script to update the database from it's current state to the latest migration
546
547.EXAMPLE
548 Update-Database -Script -SourceMigration Second -TargetMigration First
549 # Generate a script to migrate the database from a specified start migration
550 # named "Second" to a specified target migration named "First"
551
552.EXAMPLE
553 Update-Database -Script -SourceMigration $InitialDatabase
554 # Generate a script that can upgrade a database currently at any version to the latest version.
555 # The generated script includes logic to check the __MigrationsHistory table and only apply changes
556 # that haven't been previously applied.
557
558.EXAMPLE
559 Update-Database -TargetMigration $InitialDatabase
560 # Runs the Down method to roll-back any migrations that have been applied to the database
561
562
563#>
564function Update-Database
565{
566 [CmdletBinding(DefaultParameterSetName = 'ConnectionStringName')]
567 param (
568 [string] $SourceMigration,
569 [string] $TargetMigration,
570 [switch] $Script,
571 [switch] $Force,
572 [string] $ProjectName,
573 [string] $StartUpProjectName,
574 [string] $ConfigurationTypeName,
575 [parameter(ParameterSetName = 'ConnectionStringName')]
576 [string] $ConnectionStringName,
577 [parameter(ParameterSetName = 'ConnectionStringAndProviderName',
578 Mandatory = $true)]
579 [string] $ConnectionString,
580 [parameter(ParameterSetName = 'ConnectionStringAndProviderName',
581 Mandatory = $true)]
582 [string] $ConnectionProviderName,
583 [string] $AppDomainBaseDirectory)
584
585 $runner = New-MigrationsRunner $ProjectName $StartUpProjectName $null $ConfigurationTypeName $ConnectionStringName $ConnectionString $ConnectionProviderName $null $AppDomainBaseDirectory
586
587 try
588 {
589 Invoke-RunnerCommand $runner System.Data.Entity.Migrations.UpdateDatabaseCommand @( $SourceMigration, $TargetMigration, $Script.IsPresent, $Force.IsPresent, $Verbose.IsPresent )
590 $error = Get-RunnerError $runner
591
592 if ($error)
593 {
594 if ($knownExceptions -notcontains $error.TypeName)
595 {
596 Write-Host $error.StackTrace
597 }
598 else
599 {
600 Write-Verbose $error.StackTrace
601 }
602
603 throw $error.Message
604 }
605 $(Get-VSComponentModel).GetService([NuGetConsole.IPowerConsoleWindow]).Show()
606 }
607 finally
608 {
609 Remove-Runner $runner
610 }
611}
612
613<#
614.SYNOPSIS
615 Displays the migrations that have been applied to the target database.
616
617.DESCRIPTION
618 Displays the migrations that have been applied to the target database.
619
620.PARAMETER ProjectName
621 Specifies the project that contains the migration configuration type to be
622 used. If omitted, the default project selected in package manager console
623 is used.
624
625.PARAMETER StartUpProjectName
626 Specifies the configuration file to use for named connection strings. If
627 omitted, the specified project's configuration file is used.
628
629.PARAMETER ConfigurationTypeName
630 Specifies the migrations configuration to use. If omitted, migrations will
631 attempt to locate a single migrations configuration type in the target
632 project.
633
634.PARAMETER ConnectionStringName
635 Specifies the name of a connection string to use from the application's
636 configuration file.
637
638.PARAMETER ConnectionString
639 Specifies the the connection string to use. If omitted, the context's
640 default connection will be used.
641
642.PARAMETER ConnectionProviderName
643 Specifies the provider invariant name of the connection string.
644
645.PARAMETER AppDomainBaseDirectory
646 Specifies the directory to use for the app-domain that is used for running Migrations
647 code such that the app-domain is able to find all required assemblies. This is an
648 advanced option that should only be needed if the solution contains several projects
649 such that the assemblies needed for the context and configuration are not all
650 referenced from either the project containing the context or the project containing
651 the migrations.
652#>
653function Get-Migrations
654{
655 [CmdletBinding(DefaultParameterSetName = 'ConnectionStringName')]
656 param (
657 [string] $ProjectName,
658 [string] $StartUpProjectName,
659 [string] $ConfigurationTypeName,
660 [parameter(ParameterSetName = 'ConnectionStringName')]
661 [string] $ConnectionStringName,
662 [parameter(ParameterSetName = 'ConnectionStringAndProviderName',
663 Mandatory = $true)]
664 [string] $ConnectionString,
665 [parameter(ParameterSetName = 'ConnectionStringAndProviderName',
666 Mandatory = $true)]
667 [string] $ConnectionProviderName,
668 [string] $AppDomainBaseDirectory)
669
670 $runner = New-MigrationsRunner $ProjectName $StartUpProjectName $null $ConfigurationTypeName $ConnectionStringName $ConnectionString $ConnectionProviderName $null $AppDomainBaseDirectory
671
672 try
673 {
674 Invoke-RunnerCommand $runner System.Data.Entity.Migrations.GetMigrationsCommand
675 $error = Get-RunnerError $runner
676
677 if ($error)
678 {
679 if ($knownExceptions -notcontains $error.TypeName)
680 {
681 Write-Host $error.StackTrace
682 }
683 else
684 {
685 Write-Verbose $error.StackTrace
686 }
687
688 throw $error.Message
689 }
690 }
691 finally
692 {
693 Remove-Runner $runner
694 }
695}
696
697function New-MigrationsRunner($ProjectName, $StartUpProjectName, $ContextProjectName, $ConfigurationTypeName, $ConnectionStringName, $ConnectionString, $ConnectionProviderName, $ContextAssemblyName, $AppDomainBaseDirectory)
698{
699 $startUpProject = Get-MigrationsStartUpProject $StartUpProjectName $ProjectName
700
701 # Special Rock Customization to EF Powershell scripts
702 # Don't build the startUpProject (RockWeb), just build Rock.csproj instead
703 # Build-Project $startUpProject
704 $rockProject = Get-SingleProject('Rock');
705 if ($rockProject)
706 {
707 Build-Project $rockProject
708 }
709
710 $project = Get-MigrationsProject $ProjectName
711 Build-Project $project
712
713 $contextProject = $project
714 if ($ContextProjectName)
715 {
716 $contextProject = Get-SingleProject $ContextProjectName
717 Build-Project $contextProject
718 }
719
720 $installPath = Get-EntityFrameworkInstallPath $project
721 $toolsPath = Join-Path $installPath tools
722
723 $info = New-AppDomainSetup $project $installPath
724
725 $domain = [AppDomain]::CreateDomain('Migrations', $null, $info)
726 $domain.SetData('project', $project)
727 $domain.SetData('contextProject', $contextProject)
728 $domain.SetData('startUpProject', $startUpProject)
729 $domain.SetData('configurationTypeName', $ConfigurationTypeName)
730 $domain.SetData('connectionStringName', $ConnectionStringName)
731 $domain.SetData('connectionString', $ConnectionString)
732 $domain.SetData('connectionProviderName', $ConnectionProviderName)
733 $domain.SetData('contextAssemblyName', $ContextAssemblyName)
734 $domain.SetData('appDomainBaseDirectory', $AppDomainBaseDirectory)
735
736 $dispatcher = New-DomainDispatcher $toolsPath
737 $domain.SetData('efDispatcher', $dispatcher)
738
739 return @{
740 Domain = $domain;
741 ToolsPath = $toolsPath
742 }
743}
744
745function New-EFConfigRunner($Project)
746{
747 $installPath = Get-EntityFrameworkInstallPath $Project
748 $toolsPath = Join-Path $installPath tools
749 $info = New-AppDomainSetup $Project $installPath
750
751 $domain = [AppDomain]::CreateDomain('EFConfig', $null, $info)
752 $domain.SetData('project', $Project)
753
754 $dispatcher = New-DomainDispatcher $toolsPath
755 $domain.SetData('efDispatcher', $dispatcher)
756
757 return @{
758 Domain = $domain;
759 ToolsPath = $toolsPath
760 }
761}
762
763function New-AppDomainSetup($Project, $InstallPath)
764{
765 $info = New-Object System.AppDomainSetup -Property @{
766 ShadowCopyFiles = 'true';
767 ApplicationBase = $InstallPath;
768 PrivateBinPath = 'tools';
769 ConfigurationFile = ([AppDomain]::CurrentDomain.SetupInformation.ConfigurationFile)
770 }
771
772 $targetFrameworkVersion = (New-Object System.Runtime.Versioning.FrameworkName ($Project.Properties.Item('TargetFrameworkMoniker').Value)).Version
773
774 if ($targetFrameworkVersion -lt (New-Object Version @( 4, 5 )))
775 {
776 $info.PrivateBinPath += ';lib\net40'
777 }
778 else
779 {
780 $info.PrivateBinPath += ';lib\net45'
781 }
782
783 return $info
784}
785
786function New-DomainDispatcher($ToolsPath)
787{
788 $utilityAssembly = [System.Reflection.Assembly]::LoadFrom((Join-Path $ToolsPath EntityFramework.PowerShell.Utility.dll))
789 $dispatcher = $utilityAssembly.CreateInstance(
790 'System.Data.Entity.Migrations.Utilities.DomainDispatcher',
791 $false,
792 [System.Reflection.BindingFlags]::Instance -bor [System.Reflection.BindingFlags]::Public,
793 $null,
794 $PSCmdlet,
795 $null,
796 $null)
797
798 return $dispatcher
799}
800
801function Remove-Runner($runner)
802{
803 [AppDomain]::Unload($runner.Domain)
804}
805
806function Invoke-RunnerCommand($runner, $command, $parameters, $anonymousArguments)
807{
808 $domain = $runner.Domain
809
810 if ($anonymousArguments)
811 {
812 $anonymousArguments.GetEnumerator() | %{
813 $domain.SetData($_.Name, $_.Value)
814 }
815 }
816
817 $domain.CreateInstanceFrom(
818 (Join-Path $runner.ToolsPath EntityFramework.PowerShell.dll),
819 $command,
820 $false,
821 0,
822 $null,
823 $parameters,
824 $null,
825 $null) | Out-Null
826}
827
828function Get-RunnerError($runner)
829{
830 $domain = $runner.Domain
831
832 if (!$domain.GetData('wasError'))
833 {
834 return $null
835 }
836
837 return @{
838 Message = $domain.GetData('error.Message');
839 TypeName = $domain.GetData('error.TypeName');
840 StackTrace = $domain.GetData('error.StackTrace')
841 }
842}
843
844function Get-MigrationsProject($name, $hideMessage)
845{
846 if ($name)
847 {
848 return Get-SingleProject $name
849 }
850
851 $project = Get-Project
852 $projectName = $project.Name
853
854 if (!$hideMessage)
855 {
856 Write-Verbose "Using NuGet project '$projectName'."
857 }
858
859 return $project
860}
861
862function Get-MigrationsStartUpProject($name, $fallbackName)
863{
864 $startUpProject = $null
865
866 if ($name)
867 {
868 $startUpProject = Get-SingleProject $name
869 }
870 else
871 {
872 $startupProjectPaths = $DTE.Solution.SolutionBuild.StartupProjects
873
874 if ($startupProjectPaths)
875 {
876 if ($startupProjectPaths.Length -eq 1)
877 {
878 $startupProjectPath = $startupProjectPaths[0]
879
880 if (!(Split-Path -IsAbsolute $startupProjectPath))
881 {
882 $solutionPath = Split-Path $DTE.Solution.Properties.Item('Path').Value
883 $startupProjectPath = Join-Path $solutionPath $startupProjectPath -Resolve
884 }
885
886 $startupProject = Get-SolutionProjects | ?{
887 try
888 {
889 $fullName = $_.FullName
890 }
891 catch [NotImplementedException]
892 {
893 return $false
894 }
895
896 if ($fullName -and $fullName.EndsWith('\'))
897 {
898 $fullName = $fullName.Substring(0, $fullName.Length - 1)
899 }
900
901 return $fullName -eq $startupProjectPath
902 }
903 }
904 else
905 {
906 Write-Verbose 'More than one start-up project found.'
907 }
908 }
909 else
910 {
911 Write-Verbose 'No start-up project found.'
912 }
913 }
914
915 if (!($startUpProject -and (Test-StartUpProject $startUpProject)))
916 {
917 $startUpProject = Get-MigrationsProject $fallbackName $true
918 $startUpProjectName = $startUpProject.Name
919
920 Write-Warning "Cannot determine a valid start-up project. Using project '$startUpProjectName' instead. Your configuration file and working directory may not be set as expected. Use the -StartUpProjectName parameter to set one explicitly. Use the -Verbose switch for more information."
921 }
922 else
923 {
924 $startUpProjectName = $startUpProject.Name
925
926 Write-Verbose "Using StartUp project '$startUpProjectName'."
927 }
928
929 return $startUpProject
930}
931
932function Get-SolutionProjects()
933{
934 $projects = New-Object System.Collections.Stack
935
936 $DTE.Solution.Projects | %{
937 $projects.Push($_)
938 }
939
940 while ($projects.Count -ne 0)
941 {
942 $project = $projects.Pop();
943
944 # NOTE: This line is similar to doing a "yield return" in C#
945 $project
946
947 if ($project.ProjectItems)
948 {
949 $project.ProjectItems | ?{ $_.SubProject } | %{
950 $projects.Push($_.SubProject)
951 }
952 }
953 }
954}
955
956function Get-SingleProject($name)
957{
958 $project = Get-Project $name
959
960 if ($project -is [array])
961 {
962 throw "More than one project '$name' was found. Specify the full name of the one to use."
963 }
964
965 return $project
966}
967
968function Test-StartUpProject($project)
969{
970 if ($project.Kind -eq '{cc5fd16d-436d-48ad-a40c-5a424c6e3e79}')
971 {
972 $projectName = $project.Name
973 Write-Verbose "Cannot use start-up project '$projectName'. The Windows Azure Project type isn't supported."
974
975 return $false
976 }
977
978 return $true
979}
980
981function Build-Project($project)
982{
983 $configuration = $DTE.Solution.SolutionBuild.ActiveConfiguration.Name
984
985 $DTE.Solution.SolutionBuild.BuildProject($configuration, $project.UniqueName, $true)
986
987 if ($DTE.Solution.SolutionBuild.LastBuildInfo)
988 {
989 $projectName = $project.Name
990
991 throw "The project '$projectName' failed to build."
992 }
993}
994
995function Get-EntityFrameworkInstallPath($project)
996{
997 $package = Get-Package -ProjectName $project.FullName | ?{ $_.Id -eq 'EntityFramework' }
998
999 if (!$package)
1000 {
1001 $projectName = $project.Name
1002
1003 throw "The EntityFramework package is not installed on project '$projectName'."
1004 }
1005
1006 return Get-PackageInstallPath $package
1007}
1008
1009function Get-PackageInstallPath($package)
1010{
1011 $componentModel = Get-VsComponentModel
1012 $packageInstallerServices = $componentModel.GetService([NuGet.VisualStudio.IVsPackageInstallerServices])
1013
1014 $vsPackage = $packageInstallerServices.GetInstalledPackages() | ?{ $_.Id -eq $package.Id -and $_.Version -eq $package.Version }
1015
1016 return $vsPackage.InstallPath
1017}
1018
1019function Check-Project($project)
1020{
1021 if (!$project.FullName)
1022 {
1023 throw "The Project argument must refer to a Visual Studio project. Use the '`$project' variable provided by NuGet when running in install.ps1."
1024 }
1025
1026 return $project.CodeModel
1027}
1028
1029Export-ModuleMember @( 'Enable-Migrations', 'Add-Migration', 'Update-Database', 'Get-Migrations', 'Add-EFProvider', 'Add-EFDefaultConnectionFactory', 'Initialize-EFConfiguration') -Variable InitialDatabase
1030
1031# SIG # Begin signature block
1032# MIIa2AYJKoZIhvcNAQcCoIIayTCCGsUCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
1033# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
1034# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQU3poUYDlTlwf2GyqxNJ7CRJO4
1035# tk2gghV6MIIEuzCCA6OgAwIBAgITMwAAAFrtL/TkIJk/OgAAAAAAWjANBgkqhkiG
1036# 9w0BAQUFADB3MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4G
1037# A1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSEw
1038# HwYDVQQDExhNaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EwHhcNMTQwNTIzMTcxMzE1
1039# WhcNMTUwODIzMTcxMzE1WjCBqzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAldBMRAw
1040# DgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x
1041# DTALBgNVBAsTBE1PUFIxJzAlBgNVBAsTHm5DaXBoZXIgRFNFIEVTTjpCOEVDLTMw
1042# QTQtNzE0NDElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZTCC
1043# ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALMhIt9q0L/7KcnVbHqJqY0T
1044# vJS16X0pZdp/9B+rDHlhZlRhlgfw1GBLMZsJr30obdCle4dfdqHSxinHljqjXxeM
1045# duC3lgcPx2JhtLaq9kYUKQMuJrAdSgjgfdNcMBKmm/a5Dj1TFmmdu2UnQsHoMjUO
1046# 9yn/3lsgTLsvaIQkD6uRxPPOKl5YRu2pRbRptlQmkRJi/W8O5M/53D/aKWkfSq7u
1047# wIJC64Jz6VFTEb/dqx1vsgpQeAuD7xsIsxtnb9MFfaEJn8J3iKCjWMFP/2fz3uzH
1048# 9TPcikUOlkYUKIccYLf1qlpATHC1acBGyNTo4sWQ3gtlNdRUgNLpnSBWr9TfzbkC
1049# AwEAAaOCAQkwggEFMB0GA1UdDgQWBBS+Z+AuAhuvCnINOh1/jJ1rImYR9zAfBgNV
1050# HSMEGDAWgBQjNPjZUkZwCu1A+3b7syuwwzWzDzBUBgNVHR8ETTBLMEmgR6BFhkNo
1051# dHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNyb3Nv
1052# ZnRUaW1lU3RhbXBQQ0EuY3JsMFgGCCsGAQUFBwEBBEwwSjBIBggrBgEFBQcwAoY8
1053# aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNyb3NvZnRUaW1l
1054# U3RhbXBQQ0EuY3J0MBMGA1UdJQQMMAoGCCsGAQUFBwMIMA0GCSqGSIb3DQEBBQUA
1055# A4IBAQAgU4KQrqZNTn4zScizrcTDfhXQEvIPJ4p/W78+VOpB6VQDKym63VSIu7n3
1056# 2c5T7RAWPclGcLQA0fI0XaejIiyqIuFrob8PDYfQHgIb73i2iSDQLKsLdDguphD/
1057# 2pGrLEA8JhWqrN7Cz0qTA81r4qSymRpdR0Tx3IIf5ki0pmmZwS7phyPqCNJp5mLf
1058# cfHrI78hZfmkV8STLdsWeBWqPqLkhfwXvsBPFduq8Ki6ESus+is1Fm5bc/4w0Pur
1059# k6DezULaNj+R9+A3jNkHrTsnu/9UIHfG/RHpGuZpsjMnqwWuWI+mqX9dEhFoDCyj
1060# MRYNviGrnPCuGnxA1daDFhXYKPvlMIIE7DCCA9SgAwIBAgITMwAAAMps1TISNcTh
1061# VQABAAAAyjANBgkqhkiG9w0BAQUFADB5MQswCQYDVQQGEwJVUzETMBEGA1UECBMK
1062# V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0
1063# IENvcnBvcmF0aW9uMSMwIQYDVQQDExpNaWNyb3NvZnQgQ29kZSBTaWduaW5nIFBD
1064# QTAeFw0xNDA0MjIxNzM5MDBaFw0xNTA3MjIxNzM5MDBaMIGDMQswCQYDVQQGEwJV
1065# UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE
1066# ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMQ0wCwYDVQQLEwRNT1BSMR4wHAYDVQQD
1067# ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
1068# ggEKAoIBAQCWcV3tBkb6hMudW7dGx7DhtBE5A62xFXNgnOuntm4aPD//ZeM08aal
1069# IV5WmWxY5JKhClzC09xSLwxlmiBhQFMxnGyPIX26+f4TUFJglTpbuVildGFBqZTg
1070# rSZOTKGXcEknXnxnyk8ecYRGvB1LtuIPxcYnyQfmegqlFwAZTHBFOC2BtFCqxWfR
1071# +nm8xcyhcpv0JTSY+FTfEjk4Ei+ka6Wafsdi0dzP7T00+LnfNTC67HkyqeGprFVN
1072# TH9MVsMTC3bxB/nMR6z7iNVSpR4o+j0tz8+EmIZxZRHPhckJRIbhb+ex/KxARKWp
1073# iyM/gkmd1ZZZUBNZGHP/QwytK9R/MEBnAgMBAAGjggFgMIIBXDATBgNVHSUEDDAK
1074# BggrBgEFBQcDAzAdBgNVHQ4EFgQUH17iXVCNVoa+SjzPBOinh7XLv4MwUQYDVR0R
1075# BEowSKRGMEQxDTALBgNVBAsTBE1PUFIxMzAxBgNVBAUTKjMxNTk1K2I0MjE4ZjEz
1076# LTZmY2EtNDkwZi05YzQ3LTNmYzU1N2RmYzQ0MDAfBgNVHSMEGDAWgBTLEejK0rQW
1077# WAHJNy4zFha5TJoKHzBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jv
1078# c29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNDb2RTaWdQQ0FfMDgtMzEtMjAx
1079# MC5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3Lm1p
1080# Y3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY0NvZFNpZ1BDQV8wOC0zMS0yMDEwLmNy
1081# dDANBgkqhkiG9w0BAQUFAAOCAQEAd1zr15E9zb17g9mFqbBDnXN8F8kP7Tbbx7Us
1082# G177VAU6g3FAgQmit3EmXtZ9tmw7yapfXQMYKh0nfgfpxWUftc8Nt1THKDhaiOd7
1083# wRm2VjK64szLk9uvbg9dRPXUsO8b1U7Brw7vIJvy4f4nXejF/2H2GdIoCiKd381w
1084# gp4YctgjzHosQ+7/6sDg5h2qnpczAFJvB7jTiGzepAY1p8JThmURdwmPNVm52Iao
1085# AP74MX0s9IwFncDB1XdybOlNWSaD8cKyiFeTNQB8UCu8Wfz+HCk4gtPeUpdFKRhO
1086# lludul8bo/EnUOoHlehtNA04V9w3KDWVOjic1O1qhV0OIhFeezCCBbwwggOkoAMC
1087# AQICCmEzJhoAAAAAADEwDQYJKoZIhvcNAQEFBQAwXzETMBEGCgmSJomT8ixkARkW
1088# A2NvbTEZMBcGCgmSJomT8ixkARkWCW1pY3Jvc29mdDEtMCsGA1UEAxMkTWljcm9z
1089# b2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTEwMDgzMTIyMTkzMloX
1090# DTIwMDgzMTIyMjkzMloweTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0
1091# b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3Jh
1092# dGlvbjEjMCEGA1UEAxMaTWljcm9zb2Z0IENvZGUgU2lnbmluZyBQQ0EwggEiMA0G
1093# CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCycllcGTBkvx2aYCAgQpl2U2w+G9Zv
1094# zMvx6mv+lxYQ4N86dIMaty+gMuz/3sJCTiPVcgDbNVcKicquIEn08GisTUuNpb15
1095# S3GbRwfa/SXfnXWIz6pzRH/XgdvzvfI2pMlcRdyvrT3gKGiXGqelcnNW8ReU5P01
1096# lHKg1nZfHndFg4U4FtBzWwW6Z1KNpbJpL9oZC/6SdCnidi9U3RQwWfjSjWL9y8lf
1097# RjFQuScT5EAwz3IpECgixzdOPaAyPZDNoTgGhVxOVoIoKgUyt0vXT2Pn0i1i8UU9
1098# 56wIAPZGoZ7RW4wmU+h6qkryRs83PDietHdcpReejcsRj1Y8wawJXwPTAgMBAAGj
1099# ggFeMIIBWjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTLEejK0rQWWAHJNy4z
1100# Fha5TJoKHzALBgNVHQ8EBAMCAYYwEgYJKwYBBAGCNxUBBAUCAwEAATAjBgkrBgEE
1101# AYI3FQIEFgQU/dExTtMmipXhmGA7qDFvpjy82C0wGQYJKwYBBAGCNxQCBAweCgBT
1102# AHUAYgBDAEEwHwYDVR0jBBgwFoAUDqyCYEBWJ5flJRP8KuEKU5VZ5KQwUAYDVR0f
1103# BEkwRzBFoEOgQYY/aHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJv
1104# ZHVjdHMvbWljcm9zb2Z0cm9vdGNlcnQuY3JsMFQGCCsGAQUFBwEBBEgwRjBEBggr
1105# BgEFBQcwAoY4aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNy
1106# b3NvZnRSb290Q2VydC5jcnQwDQYJKoZIhvcNAQEFBQADggIBAFk5Pn8mRq/rb0Cx
1107# MrVq6w4vbqhJ9+tfde1MOy3XQ60L/svpLTGjI8x8UJiAIV2sPS9MuqKoVpzjcLu4
1108# tPh5tUly9z7qQX/K4QwXaculnCAt+gtQxFbNLeNK0rxw56gNogOlVuC4iktX8pVC
1109# nPHz7+7jhh80PLhWmvBTI4UqpIIck+KUBx3y4k74jKHK6BOlkU7IG9KPcpUqcW2b
1110# Gvgc8FPWZ8wi/1wdzaKMvSeyeWNWRKJRzfnpo1hW3ZsCRUQvX/TartSCMm78pJUT
1111# 5Otp56miLL7IKxAOZY6Z2/Wi+hImCWU4lPF6H0q70eFW6NB4lhhcyTUWX92THUmO
1112# Lb6tNEQc7hAVGgBd3TVbIc6YxwnuhQ6MT20OE049fClInHLR82zKwexwo1eSV32U
1113# jaAbSANa98+jZwp0pTbtLS8XyOZyNxL0b7E8Z4L5UrKNMxZlHg6K3RDeZPRvzkbU
1114# 0xfpecQEtNP7LN8fip6sCvsTJ0Ct5PnhqX9GuwdgR2VgQE6wQuxO7bN2edgKNAlt
1115# HIAxH+IOVN3lofvlRxCtZJj/UBYufL8FIXrilUEnacOTj5XJjdibIa4NXJzwoq6G
1116# aIMMai27dmsAHZat8hZ79haDJLmIz2qoRzEvmtzjcT3XAH5iR9HOiMm4GPoOco3B
1117# oz2vAkBq/2mbluIQqBC0N1AI1sM9MIIGBzCCA++gAwIBAgIKYRZoNAAAAAAAHDAN
1118# BgkqhkiG9w0BAQUFADBfMRMwEQYKCZImiZPyLGQBGRYDY29tMRkwFwYKCZImiZPy
1119# LGQBGRYJbWljcm9zb2Z0MS0wKwYDVQQDEyRNaWNyb3NvZnQgUm9vdCBDZXJ0aWZp
1120# Y2F0ZSBBdXRob3JpdHkwHhcNMDcwNDAzMTI1MzA5WhcNMjEwNDAzMTMwMzA5WjB3
1121# MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVk
1122# bW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSEwHwYDVQQDExhN
1123# aWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
1124# ggEKAoIBAQCfoWyx39tIkip8ay4Z4b3i48WZUSNQrc7dGE4kD+7Rp9FMrXQwIBHr
1125# B9VUlRVJlBtCkq6YXDAm2gBr6Hu97IkHD/cOBJjwicwfyzMkh53y9GccLPx754gd
1126# 6udOo6HBI1PKjfpFzwnQXq/QsEIEovmmbJNn1yjcRlOwhtDlKEYuJ6yGT1VSDOQD
1127# LPtqkJAwbofzWTCd+n7Wl7PoIZd++NIT8wi3U21StEWQn0gASkdmEScpZqiX5NMG
1128# gUqi+YSnEUcUCYKfhO1VeP4Bmh1QCIUAEDBG7bfeI0a7xC1Un68eeEExd8yb3zuD
1129# k6FhArUdDbH895uyAc4iS1T/+QXDwiALAgMBAAGjggGrMIIBpzAPBgNVHRMBAf8E
1130# BTADAQH/MB0GA1UdDgQWBBQjNPjZUkZwCu1A+3b7syuwwzWzDzALBgNVHQ8EBAMC
1131# AYYwEAYJKwYBBAGCNxUBBAMCAQAwgZgGA1UdIwSBkDCBjYAUDqyCYEBWJ5flJRP8
1132# KuEKU5VZ5KShY6RhMF8xEzARBgoJkiaJk/IsZAEZFgNjb20xGTAXBgoJkiaJk/Is
1133# ZAEZFgltaWNyb3NvZnQxLTArBgNVBAMTJE1pY3Jvc29mdCBSb290IENlcnRpZmlj
1134# YXRlIEF1dGhvcml0eYIQea0WoUqgpa1Mc1j0BxMuZTBQBgNVHR8ESTBHMEWgQ6BB
1135# hj9odHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9taWNy
1136# b3NvZnRyb290Y2VydC5jcmwwVAYIKwYBBQUHAQEESDBGMEQGCCsGAQUFBzAChjho
1137# dHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY3Jvc29mdFJvb3RD
1138# ZXJ0LmNydDATBgNVHSUEDDAKBggrBgEFBQcDCDANBgkqhkiG9w0BAQUFAAOCAgEA
1139# EJeKw1wDRDbd6bStd9vOeVFNAbEudHFbbQwTq86+e4+4LtQSooxtYrhXAstOIBNQ
1140# md16QOJXu69YmhzhHQGGrLt48ovQ7DsB7uK+jwoFyI1I4vBTFd1Pq5Lk541q1YDB
1141# 5pTyBi+FA+mRKiQicPv2/OR4mS4N9wficLwYTp2OawpylbihOZxnLcVRDupiXD8W
1142# mIsgP+IHGjL5zDFKdjE9K3ILyOpwPf+FChPfwgphjvDXuBfrTot/xTUrXqO/67x9
1143# C0J71FNyIe4wyrt4ZVxbARcKFA7S2hSY9Ty5ZlizLS/n+YWGzFFW6J1wlGysOUzU
1144# 9nm/qhh6YinvopspNAZ3GmLJPR5tH4LwC8csu89Ds+X57H2146SodDW4TsVxIxIm
1145# dgs8UoxxWkZDFLyzs7BNZ8ifQv+AeSGAnhUwZuhCEl4ayJ4iIdBD6Svpu/RIzCzU
1146# 2DKATCYqSCRfWupW76bemZ3KOm+9gSd0BhHudiG/m4LBJ1S2sWo9iaF2YbRuoROm
1147# v6pH8BJv/YoybLL+31HIjCPJZr2dHYcSZAI9La9Zj7jkIeW1sMpjtHhUBdRBLlCs
1148# lLCleKuzoJZ1GtmShxN1Ii8yqAhuoFuMJb+g74TKIdbrHk/Jmu5J4PcBZW+JC33I
1149# acjmbuqnl84xKf8OxVtc2E0bodj6L54/LlUWa8kTo/0xggTIMIIExAIBATCBkDB5
1150# MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVk
1151# bW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSMwIQYDVQQDExpN
1152# aWNyb3NvZnQgQ29kZSBTaWduaW5nIFBDQQITMwAAAMps1TISNcThVQABAAAAyjAJ
1153# BgUrDgMCGgUAoIHhMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQB
1154# gjcCAQsxDjAMBgorBgEEAYI3AgEVMCMGCSqGSIb3DQEJBDEWBBRRBMx7lzrmFHTD
1155# FOnHF79/U4hcUzCBgAYKKwYBBAGCNwIBDDFyMHCgUoBQAEUAbgB0AGkAdAB5ACAA
1156# RgByAGEAbQBlAHcAbwByAGsAIABUAG8AbwBsAHMAIABmAG8AcgAgAFYAaQBzAHUA
1157# YQBsACAAUwB0AHUAZABpAG+hGoAYaHR0cDovL21zZG4uY29tL2RhdGEvZWYgMA0G
1158# CSqGSIb3DQEBAQUABIIBAEd5PEhtVawenxHsuUSbbOUgAVuGOnlVja6G8O5u3I5v
1159# AcWqJtbqOKUkXc9HxAUMgu5cC/o9n8A7LF7T5xptiXXcxURfe4fmeJK9joz/XPRw
1160# lYLOevzn9GRfWSbJ/AtSOnjj1PKCtQ8SZq88iKnJ8SrjKF4Nu3TQR/wVR/k3SU0H
1161# 80Rm4lSJdt9NLxkYljaU8volXVDv9SoxDlplkGdePSbDUx3PWD7y5UVeHb94Z+aQ
1162# 8p/FuvncjarLeefLhOwEFfJRhCKvofgw2zJqA3q+m42uiuO0ndqbyp8HVc6kcMUu
1163# jS//9eYvnLP7UY1ApfiBLRPgEgTGSx/soOI2qXDjHiShggIoMIICJAYJKoZIhvcN
1164# AQkGMYICFTCCAhECAQEwgY4wdzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hp
1165# bmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jw
1166# b3JhdGlvbjEhMB8GA1UEAxMYTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBAhMzAAAA
1167# Wu0v9OQgmT86AAAAAABaMAkGBSsOAwIaBQCgXTAYBgkqhkiG9w0BCQMxCwYJKoZI
1168# hvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0xNTAzMDIxNzI5NThaMCMGCSqGSIb3DQEJ
1169# BDEWBBQXVgYJisiba3bvHeGxFzocarwSvzANBgkqhkiG9w0BAQUFAASCAQBwjV/u
1170# vAXQsEgY0oeyfvDyZCXIBSMgSZ4sbxAFu7ZGisn3L51Q/wWulmoPr7YiAmUkxRgU
1171# WL7hukD/WrR/iNwUToPwz9VTxZbz+i7Cjw5tpG+nL8ByWxyhEiWNDSGHUaU+THMr
1172# d2Y3mJs9u8E8sjNqHE8Vf7FzmjVn5dMrOASBmqTdXPwJP2Pm2gYta6zkss9j5N3Q
1173# MLwNDUrZ0FKtGimpe1zoI6Fan4YBKMILOL9xCqMcVMhoITM7s+tnRlngDVFxxKyN
1174# 1Mnr9ITkdiMIpbWn8s0nr/UsHRltjyPyjtfIvgiFgKLxnw87sHnloEAbksaLqlbX
1175# 6d/6I/2PpumqJR3c
1176# SIG # End signature block