EntityFramework.psm1 42 KB

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