12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406 |
- # 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
- # MIIkWAYJKoZIhvcNAQcCoIIkSTCCJEUCAQExDzANBglghkgBZQMEAgEFADB5Bgor
- # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
- # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBU8UKKdFAqCZNi
- # qPoRSiuscSg+YrZwC3TMOd7p8fuNZKCCDYEwggX/MIID56ADAgECAhMzAAABUZ6N
- # j0Bxow5BAAAAAAFRMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
- # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
- # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
- # bmcgUENBIDIwMTEwHhcNMTkwNTAyMjEzNzQ2WhcNMjAwNTAyMjEzNzQ2WjB0MQsw
- # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
- # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
- # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
- # AQCVWsaGaUcdNB7xVcNmdfZiVBhYFGcn8KMqxgNIvOZWNH9JYQLuhHhmJ5RWISy1
- # oey3zTuxqLbkHAdmbeU8NFMo49Pv71MgIS9IG/EtqwOH7upan+lIq6NOcw5fO6Os
- # +12R0Q28MzGn+3y7F2mKDnopVu0sEufy453gxz16M8bAw4+QXuv7+fR9WzRJ2CpU
- # 62wQKYiFQMfew6Vh5fuPoXloN3k6+Qlz7zgcT4YRmxzx7jMVpP/uvK6sZcBxQ3Wg
- # B/WkyXHgxaY19IAzLq2QiPiX2YryiR5EsYBq35BP7U15DlZtpSs2wIYTkkDBxhPJ
- # IDJgowZu5GyhHdqrst3OjkSRAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE
- # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUV4Iarkq57esagu6FUBb270Zijc8w
- # UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1
- # ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDU0MTM1MB8GA1UdIwQYMBaAFEhu
- # ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu
- # bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w
- # Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3
- # Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx
- # MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAWg+A
- # rS4Anq7KrogslIQnoMHSXUPr/RqOIhJX+32ObuY3MFvdlRElbSsSJxrRy/OCCZdS
- # se+f2AqQ+F/2aYwBDmUQbeMB8n0pYLZnOPifqe78RBH2fVZsvXxyfizbHubWWoUf
- # NW/FJlZlLXwJmF3BoL8E2p09K3hagwz/otcKtQ1+Q4+DaOYXWleqJrJUsnHs9UiL
- # crVF0leL/Q1V5bshob2OTlZq0qzSdrMDLWdhyrUOxnZ+ojZ7UdTY4VnCuogbZ9Zs
- # 9syJbg7ZUS9SVgYkowRsWv5jV4lbqTD+tG4FzhOwcRQwdb6A8zp2Nnd+s7VdCuYF
- # sGgI41ucD8oxVfcAMjF9YX5N2s4mltkqnUe3/htVrnxKKDAwSYliaux2L7gKw+bD
- # 1kEZ/5ozLRnJ3jjDkomTrPctokY/KaZ1qub0NUnmOKH+3xUK/plWJK8BOQYuU7gK
- # YH7Yy9WSKNlP7pKj6i417+3Na/frInjnBkKRCJ/eYTvBH+s5guezpfQWtU4bNo/j
- # 8Qw2vpTQ9w7flhH78Rmwd319+YTmhv7TcxDbWlyteaj4RK2wk3pY1oSz2JPE5PNu
- # Nmd9Gmf6oePZgy7Ii9JLLq8SnULV7b+IP0UXRY9q+GdRjM2AEX6msZvvPCIoG0aY
- # HQu9wZsKEK2jqvWi8/xdeeeSI9FN6K1w4oVQM4Mwggd6MIIFYqADAgECAgphDpDS
- # AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK
- # V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0
- # IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0
- # ZSBBdXRob3JpdHkgMjAxMTAeFw0xMTA3MDgyMDU5MDlaFw0yNjA3MDgyMTA5MDla
- # MH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS
- # ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMT
- # H01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTEwggIiMA0GCSqGSIb3DQEB
- # AQUAA4ICDwAwggIKAoICAQCr8PpyEBwurdhuqoIQTTS68rZYIZ9CGypr6VpQqrgG
- # OBoESbp/wwwe3TdrxhLYC/A4wpkGsMg51QEUMULTiQ15ZId+lGAkbK+eSZzpaF7S
- # 35tTsgosw6/ZqSuuegmv15ZZymAaBelmdugyUiYSL+erCFDPs0S3XdjELgN1q2jz
- # y23zOlyhFvRGuuA4ZKxuZDV4pqBjDy3TQJP4494HDdVceaVJKecNvqATd76UPe/7
- # 4ytaEB9NViiienLgEjq3SV7Y7e1DkYPZe7J7hhvZPrGMXeiJT4Qa8qEvWeSQOy2u
- # M1jFtz7+MtOzAz2xsq+SOH7SnYAs9U5WkSE1JcM5bmR/U7qcD60ZI4TL9LoDho33
- # X/DQUr+MlIe8wCF0JV8YKLbMJyg4JZg5SjbPfLGSrhwjp6lm7GEfauEoSZ1fiOIl
- # XdMhSz5SxLVXPyQD8NF6Wy/VI+NwXQ9RRnez+ADhvKwCgl/bwBWzvRvUVUvnOaEP
- # 6SNJvBi4RHxF5MHDcnrgcuck379GmcXvwhxX24ON7E1JMKerjt/sW5+v/N2wZuLB
- # l4F77dbtS+dJKacTKKanfWeA5opieF+yL4TXV5xcv3coKPHtbcMojyyPQDdPweGF
- # RInECUzF1KVDL3SV9274eCBYLBNdYJWaPk8zhNqwiBfenk70lrC8RqBsmNLg1oiM
- # CwIDAQABo4IB7TCCAekwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFEhuZOVQ
- # BdOCqhc3NyK1bajKdQKVMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1Ud
- # DwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFHItOgIxkEO5FAVO
- # 4eqnxzHRI4k0MFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwubWljcm9zb2Z0
- # LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y
- # Mi5jcmwwXgYIKwYBBQUHAQEEUjBQME4GCCsGAQUFBzAChkJodHRwOi8vd3d3Lm1p
- # Y3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y
- # Mi5jcnQwgZ8GA1UdIASBlzCBlDCBkQYJKwYBBAGCNy4DMIGDMD8GCCsGAQUFBwIB
- # FjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2RvY3MvcHJpbWFyeWNw
- # cy5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AcABvAGwAaQBjAHkA
- # XwBzAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAGfyhqWY
- # 4FR5Gi7T2HRnIpsLlhHhY5KZQpZ90nkMkMFlXy4sPvjDctFtg/6+P+gKyju/R6mj
- # 82nbY78iNaWXXWWEkH2LRlBV2AySfNIaSxzzPEKLUtCw/WvjPgcuKZvmPRul1LUd
- # d5Q54ulkyUQ9eHoj8xN9ppB0g430yyYCRirCihC7pKkFDJvtaPpoLpWgKj8qa1hJ
- # Yx8JaW5amJbkg/TAj/NGK978O9C9Ne9uJa7lryft0N3zDq+ZKJeYTQ49C/IIidYf
- # wzIY4vDFLc5bnrRJOQrGCsLGra7lstnbFYhRRVg4MnEnGn+x9Cf43iw6IGmYslmJ
- # aG5vp7d0w0AFBqYBKig+gj8TTWYLwLNN9eGPfxxvFX1Fp3blQCplo8NdUmKGwx1j
- # NpeG39rz+PIWoZon4c2ll9DuXWNB41sHnIc+BncG0QaxdR8UvmFhtfDcxhsEvt9B
- # xw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf0AApxbGbpT9Fdx41xtKiop96
- # eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkYS//WsyNodeav+vyL6wuA6mk7
- # r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrvQQqxP/uozKRdwaGIm1dxVk5I
- # RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIWLTCCFikCAQEwgZUwfjELMAkG
- # A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx
- # HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z
- # b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAVGejY9AcaMOQQAAAAABUTAN
- # BglghkgBZQMEAgEFAKCBrjAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor
- # BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQg2WtigxAj
- # Szfxqqdh6zz13s7WyYGwCYznISnC+usF34IwQgYKKwYBBAGCNwIBDDE0MDKgFIAS
- # AE0AaQBjAHIAbwBzAG8AZgB0oRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTAN
- # BgkqhkiG9w0BAQEFAASCAQA2S2sCreRpLI9W0DFWRPY7mNwItsQCQ+U3OmimoDrE
- # Ar/bxo9hJMLm3DlzOFqO/8djKo3gvjL5pfhclUtkgPChpYWM+6aln/J7RIb3ZNjw
- # 6lWic4QZRD0qYTVLit4i+I4Ew+CYjfmDJP7pwLppqWaqnF0T8qRk5TrzS0tQL/5p
- # lxZzUZwGMkwwB9srwUwE+hy8tZS3H1BWbJ8mumlhi9X9cDF+nL3pOFFXVPM13zs8
- # ZfvjqzlDPnOcRt2FW8kN3OloRa7bl4Lu6LEXbn8n+wbuyJKwwTCNCSU26RQesPQB
- # uqTG0L7mjmZlJsF1Ga+gefD3PqbG+df7cXzSPDNR649DoYITtzCCE7MGCisGAQQB
- # gjcDAwExghOjMIITnwYJKoZIhvcNAQcCoIITkDCCE4wCAQMxDzANBglghkgBZQME
- # AgEFADCCAVgGCyqGSIb3DQEJEAEEoIIBRwSCAUMwggE/AgEBBgorBgEEAYRZCgMB
- # MDEwDQYJYIZIAWUDBAIBBQAEINWdRiCiKsTCKKoWnNe7xytEww32lPP/4fMUMSuG
- # nDHpAgZdrfQxYwgYEzIwMTkxMTE2MDQ1MjM5LjQ4OVowBwIBAYACAfSggdSkgdEw
- # gc4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS
- # ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsT
- # IE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFs
- # ZXMgVFNTIEVTTjo3RDJFLTM3ODItQjBGNzElMCMGA1UEAxMcTWljcm9zb2Z0IFRp
- # bWUtU3RhbXAgU2VydmljZaCCDx8wggZxMIIEWaADAgECAgphCYEqAAAAAAACMA0G
- # CSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv
- # bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0
- # aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3Jp
- # dHkgMjAxMDAeFw0xMDA3MDEyMTM2NTVaFw0yNTA3MDEyMTQ2NTVaMHwxCzAJBgNV
- # BAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4w
- # HAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29m
- # dCBUaW1lLVN0YW1wIFBDQSAyMDEwMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
- # CgKCAQEAqR0NvHcRijog7PwTl/X6f2mUa3RUENWlCgCChfvtfGhLLF/Fw+Vhwna3
- # PmYrW/AVUycEMR9BGxqVHc4JE458YTBZsTBED/FgiIRUQwzXTbg4CLNC3ZOs1nMw
- # VyaCo0UN0Or1R4HNvyRgMlhgRvJYR4YyhB50YWeRX4FUsc+TTJLBxKZd0WETbijG
- # GvmGgLvfYfxGwScdJGcSchohiq9LZIlQYrFd/XcfPfBXday9ikJNQFHRD5wGPmd/
- # 9WbAA5ZEfu/QS/1u5ZrKsajyeioKMfDaTgaRtogINeh4HLDpmc085y9Euqf03GS9
- # pAHBIAmTeM38vMDJRF1eFpwBBU8iTQIDAQABo4IB5jCCAeIwEAYJKwYBBAGCNxUB
- # BAMCAQAwHQYDVR0OBBYEFNVjOlyKMZDzQ3t8RhvFM2hahW1VMBkGCSsGAQQBgjcU
- # AgQMHgoAUwB1AGIAQwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8G
- # A1UdIwQYMBaAFNX2VsuP6KJcYmjRPZSQW9fOmhjEMFYGA1UdHwRPME0wS6BJoEeG
- # RWh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jv
- # b0NlckF1dF8yMDEwLTA2LTIzLmNybDBaBggrBgEFBQcBAQROMEwwSgYIKwYBBQUH
- # MAKGPmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljUm9vQ2Vy
- # QXV0XzIwMTAtMDYtMjMuY3J0MIGgBgNVHSABAf8EgZUwgZIwgY8GCSsGAQQBgjcu
- # AzCBgTA9BggrBgEFBQcCARYxaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL1BLSS9k
- # b2NzL0NQUy9kZWZhdWx0Lmh0bTBABggrBgEFBQcCAjA0HjIgHQBMAGUAZwBhAGwA
- # XwBQAG8AbABpAGMAeQBfAFMAdABhAHQAZQBtAGUAbgB0AC4gHTANBgkqhkiG9w0B
- # AQsFAAOCAgEAB+aIUQ3ixuCYP4FxAz2do6Ehb7Prpsz1Mb7PBeKp/vpXbRkws8LF
- # Zslq3/Xn8Hi9x6ieJeP5vO1rVFcIK1GCRBL7uVOMzPRgEop2zEBAQZvcXBf/XPle
- # FzWYJFZLdO9CEMivv3/Gf/I3fVo/HPKZeUqRUgCvOA8X9S95gWXZqbVr5MfO9sp6
- # AG9LMEQkIjzP7QOllo9ZKby2/QThcJ8ySif9Va8v/rbljjO7Yl+a21dA6fHOmWaQ
- # jP9qYn/dxUoLkSbiOewZSnFjnXshbcOco6I8+n99lmqQeKZt0uGc+R38ONiU9Mal
- # CpaGpL2eGq4EQoO4tYCbIjggtSXlZOz39L9+Y1klD3ouOVd2onGqBooPiRa6YacR
- # y5rYDkeagMXQzafQ732D8OE7cQnfXXSYIghh2rBQHm+98eEA3+cxB6STOvdlR3jo
- # +KhIq/fecn5ha293qYHLpwmsObvsxsvYgrRyzR30uIUBHoD7G4kqVDmyW9rIDVWZ
- # eodzOwjmmC3qjeAzLhIp9cAvVCch98isTtoouLGp25ayp0Kiyc8ZQU3ghvkqmqMR
- # ZjDTu3QyS99je/WZii8bxyGvWbWu3EQ8l1Bx16HSxVXjad5XwdHeMMD9zOZN+w2/
- # XU/pnR4ZOC+8z1gFLu8NoFA12u8JJxzVs341Hgi62jbb01+P3nSISRIwggT1MIID
- # 3aADAgECAhMzAAABACD3XJNW1XfQAAAAAAEAMA0GCSqGSIb3DQEBCwUAMHwxCzAJ
- # BgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k
- # MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jv
- # c29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMB4XDTE5MDkwNjIwNDEwOVoXDTIwMTIw
- # NDIwNDEwOVowgc4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAw
- # DgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x
- # KTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYD
- # VQQLEx1UaGFsZXMgVFNTIEVTTjo3RDJFLTM3ODItQjBGNzElMCMGA1UEAxMcTWlj
- # cm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZTCCASIwDQYJKoZIhvcNAQEBBQADggEP
- # ADCCAQoCggEBAMnIkckxDYWl2r86ny3RRNZPgnu8mFPweH7BDSkOhGLAQO58RqX3
- # n1EH8/Z6vb3kIxVQfV9fBCv3klv1HenWK0QDRIjrgWeWA1liAVWYe+Ob1uyntMQn
- # m224xp1Rev33lwbxZU+nDohaSyebrtSIfa56YgA2jYwutY+fs/GDSGRRJXeO5N1x
- # NKe+JsVXXc0vm50L2pMlYIOnGslEDLZmxXrPl1c7GC2Dp/V+errggr5I93acDZTU
- # oY0VaGRXpt2hUm824/ExFXaQILhL9DFlqgmiHvZXukoSRyTfklLVoI3vX+I6ZMcT
- # ciD9K8Rdx6wbB51VgASO5cDnEhqb3E+eKdECAwEAAaOCARswggEXMB0GA1UdDgQW
- # BBRoV5MnLIc6idXGditSix4avdXG1zAfBgNVHSMEGDAWgBTVYzpcijGQ80N7fEYb
- # xTNoWoVtVTBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jvc29mdC5j
- # b20vcGtpL2NybC9wcm9kdWN0cy9NaWNUaW1TdGFQQ0FfMjAxMC0wNy0wMS5jcmww
- # WgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jvc29m
- # dC5jb20vcGtpL2NlcnRzL01pY1RpbVN0YVBDQV8yMDEwLTA3LTAxLmNydDAMBgNV
- # HRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMIMA0GCSqGSIb3DQEBCwUAA4IB
- # AQCifptCMXyHpJghB7zNYXmFzlzpxLlmtFAkiBOdn99EnxrCJda/EZuTt9gJROel
- # 99Iy3IUpX3y/5AIZTQHPqEISnCs9Y327HWMwkZtWNnp/PPv7V6eZhYgE5gsNwxKW
- # eH8A5oI2m8Xa3wSDCOPHCEF9IvEHaeisGY3tlU9ZlQLnj9aeJS2JqusHfsyyUYQ6
- # eX5ZQiONaTmYCwiC8oeF2QNhCKiEhb28vqpMj6HCDfL4u55u5cRME/d3YvRUgp4m
- # 02gu7Jk97u9nig5+eGH56pk7J9pkNBlXGWMATawGLUyl1N+V0yY8muWHBoAS55Lo
- # Z7Rzh4aBJoi2YH5snmzSWGskoYIDrTCCApUCAQEwgf6hgdSkgdEwgc4xCzAJBgNV
- # BAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4w
- # HAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29m
- # dCBPcGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVT
- # Tjo3RDJFLTM3ODItQjBGNzElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAg
- # U2VydmljZaIlCgEBMAkGBSsOAwIaBQADFQA4Bx/wN9XcVHYBftuNY7yzHqGMxaCB
- # 3jCB26SB2DCB1TELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAO
- # BgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEp
- # MCcGA1UECxMgTWljcm9zb2Z0IE9wZXJhdGlvbnMgUHVlcnRvIFJpY28xJzAlBgNV
- # BAsTHm5DaXBoZXIgTlRTIEVTTjo0REU5LTBDNUUtM0UwOTErMCkGA1UEAxMiTWlj
- # cm9zb2Z0IFRpbWUgU291cmNlIE1hc3RlciBDbG9jazANBgkqhkiG9w0BAQUFAAIF
- # AOF5q+IwIhgPMjAxOTExMTUyMjU3MzhaGA8yMDE5MTExNjIyNTczOFowdDA6Bgor
- # BgEEAYRZCgQBMSwwKjAKAgUA4Xmr4gIBADAHAgEAAgIhQDAHAgEAAgIbDTAKAgUA
- # 4Xr9YgIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMBoAowCAIBAAID
- # FuNgoQowCAIBAAIDB6EgMA0GCSqGSIb3DQEBBQUAA4IBAQBrXPxPFldZ3BGA7waF
- # bdOirq8oCBtE81jJO2BENnEFaxjUsbxIvoYB8odfcRNw3RjGH607OK2rY5NyJSs7
- # mx49lP0OSIQaUtm0JuIwBOD45+zpnBEHTjBce/ciO8K6olJ6Hs/iFowkrWoEgnas
- # EfDafVrHqZDKn1l17MF3XkA/Wg8a15rFphDe0H90qcWjfQOK/G4lqFpGydhAqE22
- # aOEkwHunN/sTYeFo0PK19RUQVu/Hm4mA+1zCElRa/gnWaCiT9NgTiS0JugfI16dn
- # E18OSTAIUsOQk4SYH1O5BHLutWbtZvPv8mLcv9xwOpBqkhfYNZkyRE3FGFhyiWbg
- # 3QU1MYIC9TCCAvECAQEwgZMwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hp
- # bmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jw
- # b3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAC
- # EzMAAAEAIPdck1bVd9AAAAAAAQAwDQYJYIZIAWUDBAIBBQCgggEyMBoGCSqGSIb3
- # DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQxIgQgV6mhqFSGtTlYwL+6
- # PsDgVLgoVSnoI8//MHa8YbducJAwgeIGCyqGSIb3DQEJEAIMMYHSMIHPMIHMMIGx
- # BBQ4Bx/wN9XcVHYBftuNY7yzHqGMxTCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMw
- # EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN
- # aWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0
- # YW1wIFBDQSAyMDEwAhMzAAABACD3XJNW1XfQAAAAAAEAMBYEFIE7+LoOlImaaqB1
- # i3tr5UrinFzPMA0GCSqGSIb3DQEBCwUABIIBADYOPGsSJ/BDYgITjyla3fi9ynH3
- # oKVMHzzBT71kHErwNzS+D3soFP8ySkM21R78sbWG6VBVcsyQudlKj6PqwbREElpF
- # xQti5m5XmEUzOaG4/MSnu3H1whoUBZWYvD1NQ+nATbqAGPtc0OqkJ+ULQtTs3lEr
- # oCzeEKmHUbzc40JGs00A/nZtJbAj3qUxm7XUy4GepFAB5lEqOsvCRQdTyauTkqip
- # S+nKvpjIv4N4SqViBeFseUKcHuQy4D6N5NKQK+nM5Jvlp2irax81/eCM7+/tCb6N
- # aZa64XKo7HGgzKTD3PGd9w5RGGXLGtjYxKar0mLUlp+WVR9QUTnnP2crlH0=
- # SIG # End signature block
|