123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407 |
- # Copyright (c) Microsoft Corporation. All rights reserved.
- $ErrorActionPreference = 'Stop'
- $InitialDatabase = '0'
- <#
- .SYNOPSIS
- Adds or updates an Entity Framework provider entry in the project config
- file.
- .DESCRIPTION
- Adds an entry into the 'entityFramework' section of the project config
- file for the specified provider invariant name and provider type. If an
- entry for the given invariant name already exists, then that entry is
- updated with the given type name, unless the given type name already
- matches, in which case no action is taken. The 'entityFramework'
- section is added if it does not exist. The config file is automatically
- saved if and only if a change was made.
- This command is typically used only by Entity Framework provider NuGet
- packages and is run from the 'install.ps1' script.
- .PARAMETER Project
- The Visual Studio project to update. When running in the NuGet install.ps1
- script the '$project' variable provided as part of that script should be
- used.
- .PARAMETER InvariantName
- The provider invariant name that uniquely identifies this provider. For
- example, the Microsoft SQL Server provider is registered with the invariant
- name 'System.Data.SqlClient'.
- .PARAMETER TypeName
- The assembly-qualified type name of the provider-specific type that
- inherits from 'System.Data.Entity.Core.Common.DbProviderServices'. For
- example, for the Microsoft SQL Server provider, this type is
- 'System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer'.
- #>
- function Add-EFProvider
- {
- [CmdletBinding(PositionalBinding = $false)]
- param(
- [parameter(Position = 0, Mandatory = $true)]
- $Project,
- [parameter(Position = 1, Mandatory = $true)]
- [string] $InvariantName,
- [parameter(Position = 2, Mandatory = $true)]
- [string] $TypeName)
- $configPath = GetConfigPath $Project
- if (!$configPath)
- {
- return
- }
- [xml] $configXml = Get-Content $configPath
- $providers = $configXml.configuration.entityFramework.providers
- $providers.provider |
- where invariantName -eq $InvariantName |
- %{ $providers.RemoveChild($_) | Out-Null }
- $provider = $providers.AppendChild($configXml.CreateElement('provider'))
- $provider.SetAttribute('invariantName', $InvariantName)
- $provider.SetAttribute('type', $TypeName)
- $configXml.Save($configPath)
- }
- <#
- .SYNOPSIS
- Adds or updates an Entity Framework default connection factory in the
- project config file.
- .DESCRIPTION
- Adds an entry into the 'entityFramework' section of the project config
- file for the connection factory that Entity Framework will use by default
- when creating new connections by convention. Any existing entry will be
- overridden if it does not match. The 'entityFramework' section is added if
- it does not exist. The config file is automatically saved if and only if
- a change was made.
- This command is typically used only by Entity Framework provider NuGet
- packages and is run from the 'install.ps1' script.
- .PARAMETER Project
- The Visual Studio project to update. When running in the NuGet install.ps1
- script the '$project' variable provided as part of that script should be
- used.
- .PARAMETER TypeName
- The assembly-qualified type name of the connection factory type that
- implements the 'System.Data.Entity.Infrastructure.IDbConnectionFactory'
- interface. For example, for the Microsoft SQL Server Express provider
- connection factory, this type is
- 'System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework'.
- .PARAMETER ConstructorArguments
- An optional array of strings that will be passed as arguments to the
- connection factory type constructor.
- #>
- function Add-EFDefaultConnectionFactory
- {
- [CmdletBinding(PositionalBinding = $false)]
- param(
- [parameter(Position = 0, Mandatory = $true)]
- $Project,
- [parameter(Position = 1, Mandatory = $true)]
- [string] $TypeName,
- [string[]] $ConstructorArguments)
- $configPath = GetConfigPath $Project
- if (!$configPath)
- {
- return
- }
- [xml] $configXml = Get-Content $configPath
- $entityFramework = $configXml.configuration.entityFramework
- $defaultConnectionFactory = $entityFramework.defaultConnectionFactory
- if ($defaultConnectionFactory)
- {
- $entityFramework.RemoveChild($defaultConnectionFactory) | Out-Null
- }
- $defaultConnectionFactory = $entityFramework.AppendChild($configXml.CreateElement('defaultConnectionFactory'))
- $defaultConnectionFactory.SetAttribute('type', $TypeName)
- if ($ConstructorArguments)
- {
- $parameters = $defaultConnectionFactory.AppendChild($configXml.CreateElement('parameters'))
- foreach ($constructorArgument in $ConstructorArguments)
- {
- $parameter = $parameters.AppendChild($configXml.CreateElement('parameter'))
- $parameter.SetAttribute('value', $constructorArgument)
- }
- }
- $configXml.Save($configPath)
- }
- <#
- .SYNOPSIS
- Enables Code First Migrations in a project.
- .DESCRIPTION
- Enables Migrations by scaffolding a migrations configuration class in the project. If the
- target database was created by an initializer, an initial migration will be created (unless
- automatic migrations are enabled via the EnableAutomaticMigrations parameter).
- .PARAMETER ContextTypeName
- Specifies the context to use. If omitted, migrations will attempt to locate a
- single context type in the target project.
- .PARAMETER EnableAutomaticMigrations
- Specifies whether automatic migrations will be enabled in the scaffolded migrations configuration.
- If omitted, automatic migrations will be disabled.
- .PARAMETER MigrationsDirectory
- Specifies the name of the directory that will contain migrations code files.
- If omitted, the directory will be named "Migrations".
- .PARAMETER ProjectName
- Specifies the project that the scaffolded migrations configuration class will
- be added to. If omitted, the default project selected in package manager
- console is used.
- .PARAMETER StartUpProjectName
- Specifies the configuration file to use for named connection strings. If
- omitted, the specified project's configuration file is used.
- .PARAMETER ContextProjectName
- Specifies the project which contains the DbContext class to use. If omitted,
- the context is assumed to be in the same project used for migrations.
- .PARAMETER ConnectionStringName
- Specifies the name of a connection string to use from the application's
- configuration file.
- .PARAMETER ConnectionString
- Specifies the connection string to use. If omitted, the context's
- default connection will be used.
- .PARAMETER ConnectionProviderName
- Specifies the provider invariant name of the connection string.
- .PARAMETER Force
- Specifies that the migrations configuration be overwritten when running more
- than once for a given project.
- .PARAMETER ContextAssemblyName
- Specifies the name of the assembly which contains the DbContext class to use. Use this
- parameter instead of ContextProjectName when the context is contained in a referenced
- assembly rather than in a project of the solution.
- .PARAMETER AppDomainBaseDirectory
- Specifies the directory to use for the app-domain that is used for running Migrations
- code such that the app-domain is able to find all required assemblies. This is an
- advanced option that should only be needed if the solution contains several projects
- such that the assemblies needed for the context and configuration are not all
- referenced from either the project containing the context or the project containing
- the migrations.
- .EXAMPLE
- Enable-Migrations
- # Scaffold a migrations configuration in a project with only one context
- .EXAMPLE
- Enable-Migrations -Auto
- # Scaffold a migrations configuration with automatic migrations enabled for a project
- # with only one context
- .EXAMPLE
- Enable-Migrations -ContextTypeName MyContext -MigrationsDirectory DirectoryName
- # Scaffold a migrations configuration for a project with multiple contexts
- # This scaffolds a migrations configuration for MyContext and will put the configuration
- # and subsequent configurations in a new directory called "DirectoryName"
- #>
- function Enable-Migrations
- {
- [CmdletBinding(DefaultParameterSetName = 'ConnectionStringName', PositionalBinding = $false)]
- param(
- [string] $ContextTypeName,
- [alias('Auto')]
- [switch] $EnableAutomaticMigrations,
- [string] $MigrationsDirectory,
- [string] $ProjectName,
- [string] $StartUpProjectName,
- [string] $ContextProjectName,
- [parameter(ParameterSetName = 'ConnectionStringName')]
- [string] $ConnectionStringName,
- [parameter(ParameterSetName = 'ConnectionStringAndProviderName', Mandatory = $true)]
- [string] $ConnectionString,
- [parameter(ParameterSetName = 'ConnectionStringAndProviderName', Mandatory = $true)]
- [string] $ConnectionProviderName,
- [switch] $Force,
- [string] $ContextAssemblyName,
- [string] $AppDomainBaseDirectory)
- WarnIfOtherEFs 'Enable-Migrations'
- $project = GetProject $ProjectName
- $startupProject = GetStartupProject $StartUpProjectName $project
- if (!$ContextAssemblyName -and $ContextProjectName)
- {
- $contextProject = Get-Project $ContextProjectName
- $ContextAssemblyName = GetProperty $contextProject.Properties 'AssemblyName'
- }
- $params = 'migrations', 'enable', '--json'
- if ($ContextTypeName)
- {
- $params += '--context', $ContextTypeName
- }
- if ($ContextAssemblyName)
- {
- $params += '--context-assembly', $ContextAssemblyName
- }
- if ($EnableAutomaticMigrations)
- {
- $params += '--auto'
- }
- if ($MigrationsDirectory)
- {
- $params += '--migrations-dir', $MigrationsDirectory
- }
- $params += GetParams $ConnectionStringName $ConnectionString $ConnectionProviderName
- if ($Force)
- {
- $params += '--force'
- }
- # NB: -join is here to support ConvertFrom-Json on PowerShell 3.0
- $result = (EF6 $project $startupProject $AppDomainBaseDirectory $params) -join "`n" | ConvertFrom-Json
- $project.ProjectItems.AddFromFile($result.migrationsConfiguration) | Out-Null
- $DTE.ItemOperations.OpenFile($result.migrationsConfiguration) | Out-Null
- ShowConsole
- if ($result.migration)
- {
- $project.ProjectItems.AddFromFile($result.migration) | Out-Null
- $resourcesProperties = $project.ProjectItems.AddFromFile($result.migrationResources).Properties
- $project.ProjectItems.AddFromFile($result.migrationDesigner) | Out-Null
- }
- }
- <#
- .SYNOPSIS
- Scaffolds a migration script for any pending model changes.
- .DESCRIPTION
- Scaffolds a new migration script and adds it to the project.
- .PARAMETER Name
- Specifies the name of the custom script.
- .PARAMETER Force
- Specifies that the migration user code be overwritten when re-scaffolding an
- existing migration.
- .PARAMETER ProjectName
- Specifies the project that contains the migration configuration type to be
- used. If omitted, the default project selected in package manager console
- is used.
- .PARAMETER StartUpProjectName
- Specifies the configuration file to use for named connection strings. If
- omitted, the specified project's configuration file is used.
- .PARAMETER ConfigurationTypeName
- Specifies the migrations configuration to use. If omitted, migrations will
- attempt to locate a single migrations configuration type in the target
- project.
- .PARAMETER ConnectionStringName
- Specifies the name of a connection string to use from the application's
- configuration file.
- .PARAMETER ConnectionString
- Specifies the connection string to use. If omitted, the context's
- default connection will be used.
- .PARAMETER ConnectionProviderName
- Specifies the provider invariant name of the connection string.
- .PARAMETER IgnoreChanges
- Scaffolds an empty migration ignoring any pending changes detected in the current model.
- This can be used to create an initial, empty migration to enable Migrations for an existing
- database. N.B. Doing this assumes that the target database schema is compatible with the
- current model.
- .PARAMETER AppDomainBaseDirectory
- Specifies the directory to use for the app-domain that is used for running Migrations
- code such that the app-domain is able to find all required assemblies. This is an
- advanced option that should only be needed if the solution contains several projects
- such that the assemblies needed for the context and configuration are not all
- referenced from either the project containing the context or the project containing
- the migrations.
- .EXAMPLE
- Add-Migration First
- # Scaffold a new migration named "First"
- .EXAMPLE
- Add-Migration First -IgnoreChanges
- # Scaffold an empty migration ignoring any pending changes detected in the current model.
- # This can be used to create an initial, empty migration to enable Migrations for an existing
- # database. N.B. Doing this assumes that the target database schema is compatible with the
- # current model.
- #>
- function Add-Migration
- {
- [CmdletBinding(DefaultParameterSetName = 'ConnectionStringName', PositionalBinding = $false)]
- param(
- [parameter(Position = 0, Mandatory = $true)]
- [string] $Name,
- [switch] $Force,
- [string] $ProjectName,
- [string] $StartUpProjectName,
- [string] $ConfigurationTypeName,
- [parameter(ParameterSetName = 'ConnectionStringName')]
- [string] $ConnectionStringName,
- [parameter(ParameterSetName = 'ConnectionStringAndProviderName', Mandatory = $true)]
- [string] $ConnectionString,
- [parameter(ParameterSetName = 'ConnectionStringAndProviderName', Mandatory = $true)]
- [string] $ConnectionProviderName,
- [switch] $IgnoreChanges,
- [string] $AppDomainBaseDirectory)
- WarnIfOtherEFs 'Add-Migration'
- $project = GetProject $ProjectName
- $startupProject = GetStartupProject $StartUpProjectName $project
- $params = 'migrations', 'add', $Name, '--json'
- if ($Force)
- {
- $params += '--force'
- }
- if ($ConfigurationTypeName)
- {
- $params += '--migrations-config', $ConfigurationTypeName
- }
- if ($IgnoreChanges)
- {
- $params += '--ignore-changes'
- }
- $params += GetParams $ConnectionStringName $ConnectionString $ConnectionProviderName
- # NB: -join is here to support ConvertFrom-Json on PowerShell 3.0
- $result = (EF6 $project $startupProject $AppDomainBaseDirectory $params) -join "`n" | ConvertFrom-Json
- $project.ProjectItems.AddFromFile($result.migration) | Out-Null
- $DTE.ItemOperations.OpenFile($result.migration) | Out-Null
- $resourcesProperties = $project.ProjectItems.AddFromFile($result.migrationResources).Properties
- $project.ProjectItems.AddFromFile($result.migrationDesigner) | Out-Null
- }
- <#
- .SYNOPSIS
- Applies any pending migrations to the database.
- .DESCRIPTION
- Updates the database to the current model by applying pending migrations.
- .PARAMETER SourceMigration
- Only valid with -Script. Specifies the name of a particular migration to use
- as the update's starting point. If omitted, the last applied migration in
- the database will be used.
- .PARAMETER TargetMigration
- Specifies the name of a particular migration to update the database to. If
- omitted, the current model will be used.
- .PARAMETER Script
- Generate a SQL script rather than executing the pending changes directly.
- .PARAMETER Force
- Specifies that data loss is acceptable during automatic migration of the
- database.
- .PARAMETER ProjectName
- Specifies the project that contains the migration configuration type to be
- used. If omitted, the default project selected in package manager console
- is used.
- .PARAMETER StartUpProjectName
- Specifies the configuration file to use for named connection strings. If
- omitted, the specified project's configuration file is used.
- .PARAMETER ConfigurationTypeName
- Specifies the migrations configuration to use. If omitted, migrations will
- attempt to locate a single migrations configuration type in the target
- project.
- .PARAMETER ConnectionStringName
- Specifies the name of a connection string to use from the application's
- configuration file.
- .PARAMETER ConnectionString
- Specifies the connection string to use. If omitted, the context's
- default connection will be used.
- .PARAMETER ConnectionProviderName
- Specifies the provider invariant name of the connection string.
- .PARAMETER AppDomainBaseDirectory
- Specifies the directory to use for the app-domain that is used for running Migrations
- code such that the app-domain is able to find all required assemblies. This is an
- advanced option that should only be needed if the solution contains several projects
- such that the assemblies needed for the context and configuration are not all
- referenced from either the project containing the context or the project containing
- the migrations.
- .EXAMPLE
- Update-Database
- # Update the database to the latest migration
- .EXAMPLE
- Update-Database -TargetMigration Second
- # Update database to a migration named "Second"
- # This will apply migrations if the target hasn't been applied or roll back migrations
- # if it has
- .EXAMPLE
- Update-Database -Script
- # Generate a script to update the database from its current state to the latest migration
- .EXAMPLE
- Update-Database -Script -SourceMigration Second -TargetMigration First
- # Generate a script to migrate the database from a specified start migration
- # named "Second" to a specified target migration named "First"
- .EXAMPLE
- Update-Database -Script -SourceMigration $InitialDatabase
- # Generate a script that can upgrade a database currently at any version to the latest version.
- # The generated script includes logic to check the __MigrationsHistory table and only apply changes
- # that haven't been previously applied.
- .EXAMPLE
- Update-Database -TargetMigration $InitialDatabase
- # Runs the Down method to roll-back any migrations that have been applied to the database
- #>
- function Update-Database
- {
- [CmdletBinding(DefaultParameterSetName = 'ConnectionStringName', PositionalBinding = $false)]
- param(
- [string] $SourceMigration,
- [string] $TargetMigration,
- [switch] $Script,
- [switch] $Force,
- [string] $ProjectName,
- [string] $StartUpProjectName,
- [string] $ConfigurationTypeName,
- [parameter(ParameterSetName = 'ConnectionStringName')]
- [string] $ConnectionStringName,
- [parameter(ParameterSetName = 'ConnectionStringAndProviderName', Mandatory = $true)]
- [string] $ConnectionString,
- [parameter(ParameterSetName = 'ConnectionStringAndProviderName', Mandatory = $true)]
- [string] $ConnectionProviderName,
- [string] $AppDomainBaseDirectory)
- WarnIfOtherEFs 'Update-Database'
- $project = GetProject $ProjectName
- $startupProject = GetStartupProject $StartUpProjectName $project
- $params = 'database', 'update'
- if ($SourceMigration)
- {
- $params += '--source', $SourceMigration
- }
- if ($TargetMigration)
- {
- $params += '--target', $TargetMigration
- }
- if ($Script)
- {
- $params += '--script'
- }
- if ($Force)
- {
- $params += '--force'
- }
- if ($ConfigurationTypeName)
- {
- $params += '--migrations-config', $ConfigurationTypeName
- }
- $params += GetParams $ConnectionStringName $ConnectionString $ConnectionProviderName
- $result = (EF6 $project $startupProject $AppDomainBaseDirectory $params) -join "`n"
- if ($result)
- {
- try
- {
- $window = $DTE.ItemOperations.NewFile('General\Sql File')
- $textDocument = $window.Document.Object('TextDocument')
- $editPoint = $textDocument.StartPoint.CreateEditPoint()
- $editPoint.Insert($result)
- }
- catch
- {
- $intermediatePath = GetIntermediatePath $project
- if (![IO.Path]::IsPathRooted($intermediatePath))
- {
- $projectDir = GetProperty $project.Properties 'FullPath'
- $intermediatePath = Join-Path $projectDir $intermediatePath -Resolve | Convert-Path
- }
- $fileName = [IO.Path]::ChangeExtension([IO.Path]::GetRandomFileName(), '.sql')
- $sqlFile = Join-Path $intermediatePath $fileName
- [IO.File]::WriteAllText($sqlFile, $result)
- $DTE.ItemOperations.OpenFile($sqlFile) | Out-Null
- }
- ShowConsole
- }
- }
- <#
- .SYNOPSIS
- Displays the migrations that have been applied to the target database.
- .DESCRIPTION
- Displays the migrations that have been applied to the target database.
- .PARAMETER ProjectName
- Specifies the project that contains the migration configuration type to be
- used. If omitted, the default project selected in package manager console
- is used.
- .PARAMETER StartUpProjectName
- Specifies the configuration file to use for named connection strings. If
- omitted, the specified project's configuration file is used.
- .PARAMETER ConfigurationTypeName
- Specifies the migrations configuration to use. If omitted, migrations will
- attempt to locate a single migrations configuration type in the target
- project.
- .PARAMETER ConnectionStringName
- Specifies the name of a connection string to use from the application's
- configuration file.
- .PARAMETER ConnectionString
- Specifies the connection string to use. If omitted, the context's
- default connection will be used.
- .PARAMETER ConnectionProviderName
- Specifies the provider invariant name of the connection string.
- .PARAMETER AppDomainBaseDirectory
- Specifies the directory to use for the app-domain that is used for running Migrations
- code such that the app-domain is able to find all required assemblies. This is an
- advanced option that should only be needed if the solution contains several projects
- such that the assemblies needed for the context and configuration are not all
- referenced from either the project containing the context or the project containing
- the migrations.
- #>
- function Get-Migrations
- {
- [CmdletBinding(DefaultParameterSetName = 'ConnectionStringName', PositionalBinding = $false)]
- param(
- [string] $ProjectName,
- [string] $StartUpProjectName,
- [string] $ConfigurationTypeName,
- [parameter(ParameterSetName = 'ConnectionStringName')]
- [string] $ConnectionStringName,
- [parameter(ParameterSetName = 'ConnectionStringAndProviderName', Mandatory = $true)]
- [string] $ConnectionString,
- [parameter(ParameterSetName = 'ConnectionStringAndProviderName', Mandatory = $true)]
- [string] $ConnectionProviderName,
- [string] $AppDomainBaseDirectory)
- WarnIfOtherEFs 'Get-Migrations'
- $project = GetProject $ProjectName
- $startupProject = GetStartupProject $StartUpProjectName $project
- $params = 'migrations', 'list'
- if ($ConfigurationTypeName)
- {
- $params += '--migrations-config', $ConfigurationTypeName
- }
- $params += GetParams $ConnectionStringName $ConnectionString $ConnectionProviderName
- return EF6 $project $startupProject $AppDomainBaseDirectory $params
- }
- function WarnIfOtherEFs($cmdlet)
- {
- if (Get-Module 'EntityFrameworkCore')
- {
- Write-Warning "Both Entity Framework 6 and Entity Framework Core are installed. The Entity Framework 6 tools are running. Use 'EntityFrameworkCore\$cmdlet' for Entity Framework Core."
- }
- if (Get-Module 'EntityFramework')
- {
- Write-Warning "A version of Entity Framework older than 6.3 is also installed. The newer tools are running. Use 'EntityFramework\$cmdlet' for the older version."
- }
- }
- function GetProject($projectName)
- {
- if (!$projectName)
- {
- return Get-Project
- }
- return Get-Project $projectName
- }
- function GetStartupProject($name, $fallbackProject)
- {
- if ($name)
- {
- return Get-Project $name
- }
- $startupProjectPaths = $DTE.Solution.SolutionBuild.StartupProjects
- if ($startupProjectPaths)
- {
- if ($startupProjectPaths.Length -eq 1)
- {
- $startupProjectPath = $startupProjectPaths[0]
- if (![IO.Path]::IsPathRooted($startupProjectPath))
- {
- $solutionPath = Split-Path (GetProperty $DTE.Solution.Properties 'Path')
- $startupProjectPath = Join-Path $solutionPath $startupProjectPath -Resolve | Convert-Path
- }
- $startupProject = GetSolutionProjects |
- ?{
- try
- {
- $fullName = $_.FullName
- }
- catch [NotImplementedException]
- {
- return $false
- }
- if ($fullName -and $fullName.EndsWith('\'))
- {
- $fullName = $fullName.Substring(0, $fullName.Length - 1)
- }
- return $fullName -eq $startupProjectPath
- }
- if ($startupProject)
- {
- return $startupProject
- }
- Write-Warning "Unable to resolve startup project '$startupProjectPath'."
- }
- else
- {
- Write-Warning 'Multiple startup projects set.'
- }
- }
- else
- {
- Write-Warning 'No startup project set.'
- }
- Write-Warning "Using project '$($fallbackProject.ProjectName)' as the startup project."
- return $fallbackProject
- }
- function GetSolutionProjects()
- {
- $projects = New-Object 'System.Collections.Stack'
- $DTE.Solution.Projects |
- %{ $projects.Push($_) }
- while ($projects.Count)
- {
- $project = $projects.Pop();
- <# yield return #> $project
- if ($project.ProjectItems)
- {
- $project.ProjectItems |
- ?{ $_.SubProject } |
- %{ $projects.Push($_.SubProject) }
- }
- }
- }
- function GetParams($connectionStringName, $connectionString, $connectionProviderName)
- {
- $params = @()
- if ($connectionStringName)
- {
- $params += '--connection-string-name', $connectionStringName
- }
- if ($connectionString)
- {
- $params += '--connection-string', $connectionString,
- '--connection-provider', $connectionProviderName
- }
- return $params
- }
- function ShowConsole
- {
- $componentModel = Get-VSComponentModel
- $powerConsoleWindow = $componentModel.GetService([NuGetConsole.IPowerConsoleWindow])
- $powerConsoleWindow.Show()
- }
- function WriteErrorLine($message)
- {
- try
- {
- # Call the internal API NuGet uses to display errors
- $componentModel = Get-VSComponentModel
- $powerConsoleWindow = $componentModel.GetService([NuGetConsole.IPowerConsoleWindow])
- $bindingFlags = [Reflection.BindingFlags]::Instance -bor [Reflection.BindingFlags]::NonPublic
- $activeHostInfo = $powerConsoleWindow.GetType().GetProperty('ActiveHostInfo', $bindingFlags).GetValue($powerConsoleWindow)
- $internalHost = $activeHostInfo.WpfConsole.Host
- $reportErrorMethod = $internalHost.GetType().GetMethod('ReportError', $bindingFlags, $null, [Exception], $null)
- $exception = New-Object Exception $message
- $reportErrorMethod.Invoke($internalHost, $exception)
- }
- catch
- {
- Write-Host $message -ForegroundColor DarkRed
- }
- }
- function EF6($project, $startupProject, $workingDir, $params)
- {
- $solutionBuild = $DTE.Solution.SolutionBuild
- $solutionBuild.BuildProject(
- $solutionBuild.ActiveConfiguration.Name,
- $project.UniqueName,
- <# WaitForBuildToFinish #> $true)
- if ($solutionBuild.LastBuildInfo)
- {
- throw "The project '$($project.ProjectName)' failed to build."
- }
- $projectDir = GetProperty $project.Properties 'FullPath'
- $outputPath = GetProperty $project.ConfigurationManager.ActiveConfiguration.Properties 'OutputPath'
- $targetDir = [IO.Path]::GetFullPath([IO.Path]::Combine($projectDir, $outputPath))
- $targetFrameworkMoniker = GetProperty $project.Properties 'TargetFrameworkMoniker'
- $frameworkName = New-Object 'System.Runtime.Versioning.FrameworkName' $targetFrameworkMoniker
- $targetFrameworkIdentifier = $frameworkName.Identifier
- $targetFrameworkVersion = $frameworkName.Version
- if ($targetFrameworkIdentifier -in '.NETFramework')
- {
- if ($targetFrameworkVersion -lt '4.5')
- {
- $frameworkDir = 'net40'
- }
- else
- {
- $frameworkDir = 'net45'
- }
- $platformTarget = GetPlatformTarget $project
- if ($platformTarget -eq 'x86')
- {
- $runtimeDir = 'win-x86'
- }
- elseif ($platformTarget -in 'AnyCPU', 'x64')
- {
- $runtimeDir = 'any'
- }
- else
- {
- throw "Project '$($project.ProjectName)' has an active platform of '$platformTarget'. Select a different " +
- 'platform and try again.'
- }
- $exePath = Join-Path $PSScriptRoot "$frameworkDir\$runtimeDir\ef6.exe"
- }
- elseif ($targetFrameworkIdentifier -eq '.NETCoreApp')
- {
- $exePath = (Get-Command 'dotnet').Path
- $targetName = GetProperty $project.Properties 'AssemblyName'
- $depsFile = Join-Path $targetDir ($targetName + '.deps.json')
- $projectAssetsFile = GetCpsProperty $project 'ProjectAssetsFile'
- $runtimeConfig = Join-Path $targetDir ($targetName + '.runtimeconfig.json')
- $runtimeFrameworkVersion = GetCpsProperty $project 'RuntimeFrameworkVersion'
- $efPath = Join-Path $PSScriptRoot 'netcoreapp3.0\any\ef6.dll'
- $dotnetParams = 'exec', '--depsfile', $depsFile
- if ($projectAssetsFile)
- {
- # NB: Don't use Get-Content. It doesn't handle UTF-8 without a signature
- # NB: Don't use ReadAllLines. ConvertFrom-Json won't work on PowerShell 3.0
- $projectAssets = [IO.File]::ReadAllText($projectAssetsFile) | ConvertFrom-Json
- $projectAssets.packageFolders.psobject.Properties.Name |
- %{ $dotnetParams += '--additionalprobingpath', $_.TrimEnd('\') }
- }
- if (Test-Path $runtimeConfig)
- {
- $dotnetParams += '--runtimeconfig', $runtimeConfig
- }
- elseif ($runtimeFrameworkVersion)
- {
- $dotnetParams += '--fx-version', $runtimeFrameworkVersion
- }
- $dotnetParams += $efPath
- $params = $dotnetParams + $params
- }
- else
- {
- throw "Project '$($startupProject.ProjectName)' targets framework '$targetFrameworkIdentifier'. The Entity Framework " +
- 'Package Manager Console Tools don''t support this framework.'
- }
- $targetFileName = GetProperty $project.Properties 'OutputFileName'
- $targetPath = Join-Path $targetDir $targetFileName
- $rootNamespace = GetProperty $project.Properties 'RootNamespace'
- $language = GetLanguage $project
- $params += '--verbose',
- '--no-color',
- '--prefix-output',
- '--assembly', $targetPath,
- '--project-dir', $projectDir,
- '--language', $language
- if (IsWeb $startupProject)
- {
- $startupProjectDir = GetProperty $startupProject.Properties 'FullPath'
- $params += '--data-dir', (Join-Path $startupProjectDir 'App_Data')
- }
- if ($rootNamespace)
- {
- $params += '--root-namespace', $rootNamespace
- }
- $configFile = GetConfigPath $startupProject
- if ($configFile)
- {
- $params += '--config', $configFile
- }
- if (!$workingDir)
- {
- $workingDir = $targetDir
- }
- $arguments = ToArguments $params
- $startInfo = New-Object 'System.Diagnostics.ProcessStartInfo' -Property @{
- FileName = $exePath;
- Arguments = $arguments;
- UseShellExecute = $false;
- CreateNoWindow = $true;
- RedirectStandardOutput = $true;
- StandardOutputEncoding = [Text.Encoding]::UTF8;
- RedirectStandardError = $true;
- WorkingDirectory = $workingDir;
- }
- Write-Verbose "$exePath $arguments"
- $process = [Diagnostics.Process]::Start($startInfo)
- while (($line = $process.StandardOutput.ReadLine()) -ne $null)
- {
- $level = $null
- $text = $null
- $parts = $line.Split(':', 2)
- if ($parts.Length -eq 2)
- {
- $level = $parts[0]
- $i = 0
- $count = 8 - $level.Length
- while ($i -lt $count -and $parts[1][$i] -eq ' ')
- {
- $i++
- }
- $text = $parts[1].Substring($i)
- }
- switch ($level)
- {
- 'error' { WriteErrorLine $text }
- 'warn' { Write-Warning $text }
- 'info' { Write-Host $text }
- 'data' { Write-Output $text }
- 'verbose' { Write-Verbose $text }
- default { Write-Host $line }
- }
- }
- $process.WaitForExit()
- if ($process.ExitCode)
- {
- while (($line = $process.StandardError.ReadLine()) -ne $null)
- {
- WriteErrorLine $line
- }
- exit
- }
- }
- function IsCpsProject($project)
- {
- $hierarchy = GetVsHierarchy $project
- $isCapabilityMatch = [Microsoft.VisualStudio.Shell.PackageUtilities].GetMethod(
- 'IsCapabilityMatch',
- [type[]]([Microsoft.VisualStudio.Shell.Interop.IVsHierarchy], [string]))
- return $isCapabilityMatch.Invoke($null, ($hierarchy, 'CPS'))
- }
- function IsWeb($project)
- {
- $hierarchy = GetVsHierarchy $project
- $aggregatableProject = Get-Interface $hierarchy 'Microsoft.VisualStudio.Shell.Interop.IVsAggregatableProject'
- if (!$aggregatableProject)
- {
- $projectTypes = $project.Kind
- }
- else
- {
- $projectTypeGuids = $null
- $hr = $aggregatableProject.GetAggregateProjectTypeGuids([ref] $projectTypeGuids)
- [Runtime.InteropServices.Marshal]::ThrowExceptionForHR($hr)
- $projectTypes = $projectTypeGuids.Split(';')
- }
- foreach ($projectType in $projectTypes)
- {
- if ($projectType -in '{349C5851-65DF-11DA-9384-00065B846F21}', '{E24C65DC-7377-472B-9ABA-BC803B73C61A}')
- {
- return $true
- }
- }
- return $false;
- }
- function GetIntermediatePath($project)
- {
- $intermediatePath = GetProperty $project.ConfigurationManager.ActiveConfiguration.Properties 'IntermediatePath'
- if ($intermediatePath)
- {
- return $intermediatePath
- }
- return GetMSBuildProperty $project 'IntermediateOutputPath'
- }
- function GetPlatformTarget($project)
- {
- if (IsCpsProject $project)
- {
- $platformTarget = GetCpsProperty $project 'PlatformTarget'
- if ($platformTarget)
- {
- return $platformTarget
- }
- return GetCpsProperty $project 'Platform'
- }
- $platformTarget = GetProperty $project.ConfigurationManager.ActiveConfiguration.Properties 'PlatformTarget'
- if ($platformTarget)
- {
- return $platformTarget
- }
- # NB: For classic F# projects
- $platformTarget = GetMSBuildProperty $project 'PlatformTarget'
- if ($platformTarget)
- {
- return $platformTarget
- }
- return 'AnyCPU'
- }
- function GetLanguage($project)
- {
- if (IsCpsProject $project)
- {
- return GetCpsProperty $project 'Language'
- }
- return GetMSBuildProperty $project 'Language'
- }
- function GetVsHierarchy($project)
- {
- $solution = Get-VSService 'Microsoft.VisualStudio.Shell.Interop.SVsSolution' 'Microsoft.VisualStudio.Shell.Interop.IVsSolution'
- $hierarchy = $null
- $hr = $solution.GetProjectOfUniqueName($project.UniqueName, [ref] $hierarchy)
- [Runtime.InteropServices.Marshal]::ThrowExceptionForHR($hr)
- return $hierarchy
- }
- function GetProperty($properties, $propertyName)
- {
- try
- {
- return $properties.Item($propertyName).Value
- }
- catch
- {
- return $null
- }
- }
- function GetCpsProperty($project, $propertyName)
- {
- $browseObjectContext = Get-Interface $project 'Microsoft.VisualStudio.ProjectSystem.Properties.IVsBrowseObjectContext'
- $unconfiguredProject = $browseObjectContext.UnconfiguredProject
- $configuredProject = $unconfiguredProject.GetSuggestedConfiguredProjectAsync().Result
- $properties = $configuredProject.Services.ProjectPropertiesProvider.GetCommonProperties()
- return $properties.GetEvaluatedPropertyValueAsync($propertyName).Result
- }
- function GetMSBuildProperty($project, $propertyName)
- {
- $msbuildProject = [Microsoft.Build.Evaluation.ProjectCollection]::GlobalProjectCollection.LoadedProjects |
- where FullPath -eq $project.FullName
- return $msbuildProject.GetProperty($propertyName).EvaluatedValue
- }
- function ToArguments($params)
- {
- $arguments = ''
- for ($i = 0; $i -lt $params.Length; $i++)
- {
- if ($i)
- {
- $arguments += ' '
- }
- if (!$params[$i].Contains(' '))
- {
- $arguments += $params[$i]
- continue
- }
- $arguments += '"'
- $pendingBackslashs = 0
- for ($j = 0; $j -lt $params[$i].Length; $j++)
- {
- switch ($params[$i][$j])
- {
- '"'
- {
- if ($pendingBackslashs)
- {
- $arguments += '\' * $pendingBackslashs * 2
- $pendingBackslashs = 0
- }
- $arguments += '\"'
- }
- '\'
- {
- $pendingBackslashs++
- }
- default
- {
- if ($pendingBackslashs)
- {
- if ($pendingBackslashs -eq 1)
- {
- $arguments += '\'
- }
- else
- {
- $arguments += '\' * $pendingBackslashs * 2
- }
- $pendingBackslashs = 0
- }
- $arguments += $params[$i][$j]
- }
- }
- }
- if ($pendingBackslashs)
- {
- $arguments += '\' * $pendingBackslashs * 2
- }
- $arguments += '"'
- }
- return $arguments
- }
- function GetConfigPath($project)
- {
- if (IsWeb $project)
- {
- $configFileName = 'web.config'
- }
- else
- {
- $configFileName = 'app.config'
- }
- $item = $project.ProjectItems |
- where Name -eq $configFileName |
- select -First 1
- return GetProperty $item.Properties 'FullPath'
- }
- Export-ModuleMember 'Add-EFDefaultConnectionFactory', 'Add-EFProvider', 'Add-Migration', 'Enable-Migrations', 'Get-Migrations', 'Update-Database' -Variable 'InitialDatabase'
- # SIG # Begin signature block
- # MIIkXwYJKoZIhvcNAQcCoIIkUDCCJEwCAQExDzANBglghkgBZQMEAgEFADB5Bgor
- # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
- # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBU8UKKdFAqCZNi
- # qPoRSiuscSg+YrZwC3TMOd7p8fuNZKCCDYUwggYDMIID66ADAgECAhMzAAABUptA
- # n1BWmXWIAAAAAAFSMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
- # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
- # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
- # bmcgUENBIDIwMTEwHhcNMTkwNTAyMjEzNzQ2WhcNMjAwNTAyMjEzNzQ2WjB0MQsw
- # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
- # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
- # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
- # AQCxp4nT9qfu9O10iJyewYXHlN+WEh79Noor9nhM6enUNbCbhX9vS+8c/3eIVazS
- # YnVBTqLzW7xWN1bCcItDbsEzKEE2BswSun7J9xCaLwcGHKFr+qWUlz7hh9RcmjYS
- # kOGNybOfrgj3sm0DStoK8ljwEyUVeRfMHx9E/7Ca/OEq2cXBT3L0fVnlEkfal310
- # EFCLDo2BrE35NGRjG+/nnZiqKqEh5lWNk33JV8/I0fIcUKrLEmUGrv0CgC7w2cjm
- # bBhBIJ+0KzSnSWingXol/3iUdBBy4QQNH767kYGunJeY08RjHMIgjJCdAoEM+2mX
- # v1phaV7j+M3dNzZ/cdsz3oDfAgMBAAGjggGCMIIBfjAfBgNVHSUEGDAWBgorBgEE
- # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQU3f8Aw1sW72WcJ2bo/QSYGzVrRYcw
- # VAYDVR0RBE0wS6RJMEcxLTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJh
- # dGlvbnMgTGltaXRlZDEWMBQGA1UEBRMNMjMwMDEyKzQ1NDEzNjAfBgNVHSMEGDAW
- # gBRIbmTlUAXTgqoXNzcitW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8v
- # d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIw
- # MTEtMDctMDguY3JsMGEGCCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDov
- # L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDEx
- # XzIwMTEtMDctMDguY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIB
- # AJTwROaHvogXgixWjyjvLfiRgqI2QK8GoG23eqAgNjX7V/WdUWBbs0aIC3k49cd0
- # zdq+JJImixcX6UOTpz2LZPFSh23l0/Mo35wG7JXUxgO0U+5drbQht5xoMl1n7/TQ
- # 4iKcmAYSAPxTq5lFnoV2+fAeljVA7O43szjs7LR09D0wFHwzZco/iE8Hlakl23ZT
- # 7FnB5AfU2hwfv87y3q3a5qFiugSykILpK0/vqnlEVB0KAdQVzYULQ/U4eFEjnis3
- # Js9UrAvtIhIs26445Rj3UP6U4GgOjgQonlRA+mDlsh78wFSGbASIvK+fkONUhvj8
- # B8ZHNn4TFfnct+a0ZueY4f6aRPxr8beNSUKn7QW/FQmn422bE7KfnqWncsH7vbNh
- # G929prVHPsaa7J22i9wyHj7m0oATXJ+YjfyoEAtd5/NyIYaE4Uu0j1EhuYUo5VaJ
- # JnMaTER0qX8+/YZRWrFN/heps41XNVjiAawpbAa0fUa3R9RNBjPiBnM0gvNPorM4
- # dsV2VJ8GluIQOrJlOvuCrOYDGirGnadOmQ21wPBoGFCWpK56PxzliKsy5NNmAXcE
- # x7Qb9vUjY1WlYtrdwOXTpxN4slzIht69BaZlLIjLVWwqIfuNrhHKNDM9K+v7vgrI
- # bf7l5/665g0gjQCDCN6Q5sxuttTAEKtJeS/pkpI+DbZ/MIIHejCCBWKgAwIBAgIK
- # YQ6Q0gAAAAAAAzANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNV
- # BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv
- # c29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlm
- # aWNhdGUgQXV0aG9yaXR5IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEw
- # OTA5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE
- # BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYD
- # VQQDEx9NaWNyb3NvZnQgQ29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG
- # 9w0BAQEFAAOCAg8AMIICCgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+la
- # UKq4BjgaBEm6f8MMHt03a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc
- # 6Whe0t+bU7IKLMOv2akrrnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4D
- # dato88tt8zpcoRb0RrrgOGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+
- # lD3v++MrWhAfTVYoonpy4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nk
- # kDstrjNYxbc+/jLTswM9sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6
- # A4aN91/w0FK/jJSHvMAhdCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmd
- # X4jiJV3TIUs+UsS1Vz8kA/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL
- # 5zmhD+kjSbwYuER8ReTBw3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zd
- # sGbiwZeBe+3W7UvnSSmnEyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3
- # T8HhhUSJxAlMxdSlQy90lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS
- # 4NaIjAsCAwEAAaOCAe0wggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRI
- # bmTlUAXTgqoXNzcitW2oynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTAL
- # BgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBD
- # uRQFTuHqp8cx0SOJNDBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jv
- # c29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf
- # MDNfMjIuY3JsMF4GCCsGAQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3
- # dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf
- # MDNfMjIuY3J0MIGfBgNVHSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEF
- # BQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1h
- # cnljcHMuaHRtMEAGCCsGAQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkA
- # YwB5AF8AcwB0AGEAdABlAG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn
- # 8oalmOBUeRou09h0ZyKbC5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7
- # v0epo/Np22O/IjWll11lhJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0b
- # pdS1HXeUOeLpZMlEPXh6I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/
- # KmtYSWMfCWluWpiW5IP0wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvy
- # CInWH8MyGOLwxS3OW560STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBp
- # mLJZiWhub6e3dMNABQamASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJi
- # hsMdYzaXht/a8/jyFqGaJ+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYb
- # BL7fQccOKO7eZS/sl/ahXJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbS
- # oqKfenoi+kiVH6v7RyOA9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sL
- # gOppO6/8MO0ETI7f33VtY5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtX
- # cVZOSEXAQsmbdlsKgEhr/Xmfwb1tbWrJUnMTDXpQzTGCFjAwghYsAgEBMIGVMH4x
- # CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt
- # b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01p
- # Y3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTECEzMAAAFSm0CfUFaZdYgAAAAA
- # AVIwDQYJYIZIAWUDBAIBBQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQw
- # HAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEINlr
- # YoMQI0s38aqnYes89d7O1smBsAmM5yEpwvrrBd+CMEIGCisGAQQBgjcCAQwxNDAy
- # oBSAEgBNAGkAYwByAG8AcwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5j
- # b20wDQYJKoZIhvcNAQEBBQAEggEAA4wFr+j9nOalk2Cbg/LovvaZmWFRfopTwGj9
- # QbzMUO6cby0vTfP/4Mn2UI603aPDCIt96YavP5mbGk2oIHe51CZLRkVZyv2dO0l4
- # McDfHEbRYUQ7Ya9FEfpF9FJ5sieT8hKbqkj0ajqLAHEmW6kVmioXqj0xQya3j5zI
- # 7t2WnMIDsUNLWYI3dlLo50rPd87ZVxWnDIE2IVhyMMtsK5urrL4WYcgGjT8jihVE
- # FbQo9nL5y1hWd0ZSGMfLwCoVmDq4wVki9f5WjT/gPkrS/F+TrP+GZZPvyrhf0PTN
- # R0BJPgugbrZr/lfPpPfb8r367uJYNIq0ChMNLrUdmAUWLQn23aGCE7owghO2Bgor
- # BgEEAYI3AwMBMYITpjCCE6IGCSqGSIb3DQEHAqCCE5MwghOPAgEDMQ8wDQYJYIZI
- # AWUDBAIBBQAwggFYBgsqhkiG9w0BCRABBKCCAUcEggFDMIIBPwIBAQYKKwYBBAGE
- # WQoDATAxMA0GCWCGSAFlAwQCAQUABCARzTf7SSdAq/qlhyAN9oDwFAkk/oxC+YnX
- # h2AQyOBq8gIGXno7qpjuGBMyMDIwMDQxNjIyMTM0MC45NDFaMAcCAQGAAgH0oIHU
- # pIHRMIHOMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE
- # BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSkwJwYD
- # VQQLEyBNaWNyb3NvZnQgT3BlcmF0aW9ucyBQdWVydG8gUmljbzEmMCQGA1UECxMd
- # VGhhbGVzIFRTUyBFU046NTg0Ny1GNzYxLTRGNzAxJTAjBgNVBAMTHE1pY3Jvc29m
- # dCBUaW1lLVN0YW1wIFNlcnZpY2Wggg8iMIIE9TCCA92gAwIBAgITMwAAAQUHOepZ
- # 81W/KgAAAAABBTANBgkqhkiG9w0BAQsFADB8MQswCQYDVQQGEwJVUzETMBEGA1UE
- # CBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9z
- # b2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQ
- # Q0EgMjAxMDAeFw0xOTA5MDYyMDQxMThaFw0yMDEyMDQyMDQxMThaMIHOMQswCQYD
- # VQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEe
- # MBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSkwJwYDVQQLEyBNaWNyb3Nv
- # ZnQgT3BlcmF0aW9ucyBQdWVydG8gUmljbzEmMCQGA1UECxMdVGhhbGVzIFRTUyBF
- # U046NTg0Ny1GNzYxLTRGNzAxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1w
- # IFNlcnZpY2UwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMIpZjVUiL
- # WQGqDFLLaeGfhc9bxCwi8HQx+gcaF5Zz2GodhM71oyjal6uqnRM8QHxj49uKFmY/
- # SWEhlV+so3IrmEHVLmskeEQaio5PxVgUWRm+sBIJpS9GjwKrGPZ2ub4ST2J9fu5F
- # xbfTmJyB2AL6W7WcSUON8tyuz2/NRAII6YuojdMa6mjVXamL2AS7PBo1GW4Pa4Xb
- # NhEQoA4/siS4JGbcfAwVMGv87bhKapDqpXLbDq6LbFdLAv7Q7eUHiHS4eccXRNGA
- # npkdhHOK7s1O9FqpRZYsbx/UpkaoyqiQe/JFTA+1keYZsZgaQqgPNpGYD50SDDyQ
- # Z2vtNx7KVgXtAgMBAAGjggEbMIIBFzAdBgNVHQ4EFgQUPXQb/rp3KEzK6DYOy3Fn
- # /QIzNyIwHwYDVR0jBBgwFoAU1WM6XIoxkPNDe3xGG8UzaFqFbVUwVgYDVR0fBE8w
- # TTBLoEmgR4ZFaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVj
- # dHMvTWljVGltU3RhUENBXzIwMTAtMDctMDEuY3JsMFoGCCsGAQUFBwEBBE4wTDBK
- # BggrBgEFBQcwAoY+aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9N
- # aWNUaW1TdGFQQ0FfMjAxMC0wNy0wMS5jcnQwDAYDVR0TAQH/BAIwADATBgNVHSUE
- # DDAKBggrBgEFBQcDCDANBgkqhkiG9w0BAQsFAAOCAQEAp85hd3trAVfmVAPmcOAq
- # nM47TbWB9S0ySGG/eNvIfhgYC0YjCLEZhiiQyOeRTws0lIOWGv7tM5tr70RGzNo1
- # /C7SQadqQ2dT5sUj7Ga6LHO2excdzRvUIwdeOaVuaj4VpiXnhjPBRu2CVNGXPe1d
- # 7Zzw7di8xh2D6ooZBjhHLh7yGf2ZFjBjLcDVjrfaLwd4YqefJgg42s8EMUoXzsTp
- # PlS0IBKWeX+RbBycOUhXpK9qlvFbBQGp4N+uLEV6haG33oVOtWwrbhu5F0E4UDzs
- # FUaZ8OALyKraR1dIo+ZU+zjpn3Na7KUkrT/1UFYdnWYwoUDm9e+DmBhqdhUlxIhR
- # nzCCBnEwggRZoAMCAQICCmEJgSoAAAAAAAIwDQYJKoZIhvcNAQELBQAwgYgxCzAJ
- # BgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k
- # MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jv
- # c29mdCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDEwMB4XDTEwMDcwMTIx
- # MzY1NVoXDTI1MDcwMTIxNDY1NVowfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh
- # c2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBD
- # b3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIw
- # MTAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpHQ28dxGKOiDs/BOX
- # 9fp/aZRrdFQQ1aUKAIKF++18aEssX8XD5WHCdrc+Zitb8BVTJwQxH0EbGpUdzgkT
- # jnxhMFmxMEQP8WCIhFRDDNdNuDgIs0Ldk6zWczBXJoKjRQ3Q6vVHgc2/JGAyWGBG
- # 8lhHhjKEHnRhZ5FfgVSxz5NMksHEpl3RYRNuKMYa+YaAu99h/EbBJx0kZxJyGiGK
- # r0tkiVBisV39dx898Fd1rL2KQk1AUdEPnAY+Z3/1ZsADlkR+79BL/W7lmsqxqPJ6
- # Kgox8NpOBpG2iAg16HgcsOmZzTznL0S6p/TcZL2kAcEgCZN4zfy8wMlEXV4WnAEF
- # TyJNAgMBAAGjggHmMIIB4jAQBgkrBgEEAYI3FQEEAwIBADAdBgNVHQ4EFgQU1WM6
- # XIoxkPNDe3xGG8UzaFqFbVUwGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwCwYD
- # VR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU1fZWy4/oolxi
- # aNE9lJBb186aGMQwVgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDovL2NybC5taWNyb3Nv
- # ZnQuY29tL3BraS9jcmwvcHJvZHVjdHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMu
- # Y3JsMFoGCCsGAQUFBwEBBE4wTDBKBggrBgEFBQcwAoY+aHR0cDovL3d3dy5taWNy
- # b3NvZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcnQw
- # gaAGA1UdIAEB/wSBlTCBkjCBjwYJKwYBBAGCNy4DMIGBMD0GCCsGAQUFBwIBFjFo
- # dHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vUEtJL2RvY3MvQ1BTL2RlZmF1bHQuaHRt
- # MEAGCCsGAQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAFAAbwBsAGkAYwB5AF8AUwB0
- # AGEAdABlAG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQAH5ohRDeLG4Jg/
- # gXEDPZ2joSFvs+umzPUxvs8F4qn++ldtGTCzwsVmyWrf9efweL3HqJ4l4/m87WtU
- # VwgrUYJEEvu5U4zM9GASinbMQEBBm9xcF/9c+V4XNZgkVkt070IQyK+/f8Z/8jd9
- # Wj8c8pl5SpFSAK84Dxf1L3mBZdmptWvkx872ynoAb0swRCQiPM/tA6WWj1kpvLb9
- # BOFwnzJKJ/1Vry/+tuWOM7tiX5rbV0Dp8c6ZZpCM/2pif93FSguRJuI57BlKcWOd
- # eyFtw5yjojz6f32WapB4pm3S4Zz5Hfw42JT0xqUKloakvZ4argRCg7i1gJsiOCC1
- # JeVk7Pf0v35jWSUPei45V3aicaoGig+JFrphpxHLmtgOR5qAxdDNp9DvfYPw4Ttx
- # Cd9ddJgiCGHasFAeb73x4QDf5zEHpJM692VHeOj4qEir995yfmFrb3epgcunCaw5
- # u+zGy9iCtHLNHfS4hQEegPsbiSpUObJb2sgNVZl6h3M7COaYLeqN4DMuEin1wC9U
- # JyH3yKxO2ii4sanblrKnQqLJzxlBTeCG+SqaoxFmMNO7dDJL32N79ZmKLxvHIa9Z
- # ta7cRDyXUHHXodLFVeNp3lfB0d4wwP3M5k37Db9dT+mdHhk4L7zPWAUu7w2gUDXa
- # 7wknHNWzfjUeCLraNtvTX4/edIhJEqGCA7AwggKYAgEBMIH+oYHUpIHRMIHOMQsw
- # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
- # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSkwJwYDVQQLEyBNaWNy
- # b3NvZnQgT3BlcmF0aW9ucyBQdWVydG8gUmljbzEmMCQGA1UECxMdVGhhbGVzIFRT
- # UyBFU046NTg0Ny1GNzYxLTRGNzAxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0
- # YW1wIFNlcnZpY2WiJQoBATAJBgUrDgMCGgUAAxUA0nmc7MiH2Pr0x33n13Zg4RlV
- # 9qqggd4wgdukgdgwgdUxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u
- # MRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp
- # b24xKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1ZXJ0byBSaWNvMScw
- # JQYDVQQLEx5uQ2lwaGVyIE5UUyBFU046NERFOS0wQzVFLTNFMDkxKzApBgNVBAMT
- # Ik1pY3Jvc29mdCBUaW1lIFNvdXJjZSBNYXN0ZXIgQ2xvY2swDQYJKoZIhvcNAQEF
- # BQACBQDiQwziMCIYDzIwMjAwNDE3MDA1NzA2WhgPMjAyMDA0MTgwMDU3MDZaMHcw
- # PQYKKwYBBAGEWQoEATEvMC0wCgIFAOJDDOICAQAwCgIBAAICGcICAf8wBwIBAAIC
- # GH4wCgIFAOJEXmICAQAwNgYKKwYBBAGEWQoEAjEoMCYwDAYKKwYBBAGEWQoDAaAK
- # MAgCAQACAxbjYKEKMAgCAQACAwehIDANBgkqhkiG9w0BAQUFAAOCAQEATA6xpN+7
- # +epEr0I3lwl33d7P6eYuhfTZxDtgP5dr9jnFv/10jXgI47Qs0KHY4jwkeLZ9ExCM
- # muBD0RcyOx/T0xkUANz57TNPssoqTztK5hHmt6ZmwTNyzUYxVJ8ARFPp62WhWiJ9
- # Tt9vKtuPrDIuVuHzxjY63QEPhZ1+UYAnQwu+DT1XPG1rikQOEXBM9MkzTgD/8AxY
- # prHt87u+g7MObUd0t1sAyJI+0lzgJRlqeEAw5pW4CfkzGfEGXPgT/HfjWVIc176l
- # C0ntYiOma8s4znFps5hAgnxSApopGy9c9QuuNuOfiSNa3/L5ws6RYulq/qHTuifW
- # gZ90UMQ7TrA2VjGCAvUwggLxAgEBMIGTMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQI
- # EwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3Nv
- # ZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBD
- # QSAyMDEwAhMzAAABBQc56lnzVb8qAAAAAAEFMA0GCWCGSAFlAwQCAQUAoIIBMjAa
- # BgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwLwYJKoZIhvcNAQkEMSIEIEIjFCBe
- # 4MtXOBW+4EQjXEL8OLx5+eGw0ZT8w0o9gW4DMIHiBgsqhkiG9w0BCRACDDGB0jCB
- # zzCBzDCBsQQU0nmc7MiH2Pr0x33n13Zg4RlV9qowgZgwgYCkfjB8MQswCQYDVQQG
- # EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG
- # A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQg
- # VGltZS1TdGFtcCBQQ0EgMjAxMAITMwAAAQUHOepZ81W/KgAAAAABBTAWBBS6OC+C
- # 8E5t3KIl3SZn6YRcv4X++TANBgkqhkiG9w0BAQsFAASCAQBtzHRroeehPY5IFmFC
- # 0CCu+fgjt2iyDYX1P1rHZUyU1YseSFj4GEaOj5vSW2VKxlJzVl0C5/xZjQCZ73+j
- # xRFZaUKSVkh5rPDV7++x6wUcCYAfj+b0QwRh5XH3HYMB8HUwusbG2WRnZCpjmrB6
- # EQfRZcvyWiD+Lcc+QXgt0/JyOEtVpMIfwWclbYX3wltt9H3Q1PXQy5pf26A5Yu6Q
- # 58h3xsTXCXyJZ3jUrP6qImMS4KrsXrgh6OQWczyL3E+dzOm2OvF8QfErkK0ooXGh
- # zbodmkxNfq4WhN/BpRMKsRi8QdURQ1q3qLB2GJ4JjgLBzkhXvEtWD1xqF9AINmTe
- # 3n5C
- # SIG # End signature block
|