EntityFramework.psm1 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176
  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. Hint-Downgrade $MyInvocation.MyCommand
  377. $runner = New-MigrationsRunner $ProjectName $StartUpProjectName $null $ConfigurationTypeName $ConnectionStringName $ConnectionString $ConnectionProviderName $null $AppDomainBaseDirectory
  378. try
  379. {
  380. Invoke-RunnerCommand $runner System.Data.Entity.Migrations.AddMigrationCommand @( $Name, $Force.IsPresent, $IgnoreChanges.IsPresent )
  381. $error = Get-RunnerError $runner
  382. if ($error)
  383. {
  384. if ($knownExceptions -notcontains $error.TypeName)
  385. {
  386. Write-Host $error.StackTrace
  387. }
  388. else
  389. {
  390. Write-Verbose $error.StackTrace
  391. }
  392. throw $error.Message
  393. }
  394. $(Get-VSComponentModel).GetService([NuGetConsole.IPowerConsoleWindow]).Show()
  395. }
  396. finally
  397. {
  398. Remove-Runner $runner
  399. }
  400. }
  401. <#
  402. .SYNOPSIS
  403. Applies any pending migrations to the database.
  404. .DESCRIPTION
  405. Updates the database to the current model by applying pending migrations.
  406. .PARAMETER SourceMigration
  407. Only valid with -Script. Specifies the name of a particular migration to use
  408. as the update's starting point. If omitted, the last applied migration in
  409. the database will be used.
  410. .PARAMETER TargetMigration
  411. Specifies the name of a particular migration to update the database to. If
  412. omitted, the current model will be used.
  413. .PARAMETER Script
  414. Generate a SQL script rather than executing the pending changes directly.
  415. .PARAMETER Force
  416. Specifies that data loss is acceptable during automatic migration of the
  417. database.
  418. .PARAMETER ProjectName
  419. Specifies the project that contains the migration configuration type to be
  420. used. If omitted, the default project selected in package manager console
  421. is used.
  422. .PARAMETER StartUpProjectName
  423. Specifies the configuration file to use for named connection strings. If
  424. omitted, the specified project's configuration file is used.
  425. .PARAMETER ConfigurationTypeName
  426. Specifies the migrations configuration to use. If omitted, migrations will
  427. attempt to locate a single migrations configuration type in the target
  428. project.
  429. .PARAMETER ConnectionStringName
  430. Specifies the name of a connection string to use from the application's
  431. configuration file.
  432. .PARAMETER ConnectionString
  433. Specifies the the connection string to use. If omitted, the context's
  434. default connection will be used.
  435. .PARAMETER ConnectionProviderName
  436. Specifies the provider invariant name of the connection string.
  437. .PARAMETER AppDomainBaseDirectory
  438. Specifies the directory to use for the app-domain that is used for running Migrations
  439. code such that the app-domain is able to find all required assemblies. This is an
  440. advanced option that should only be needed if the solution contains several projects
  441. such that the assemblies needed for the context and configuration are not all
  442. referenced from either the project containing the context or the project containing
  443. the migrations.
  444. .EXAMPLE
  445. Update-Database
  446. # Update the database to the latest migration
  447. .EXAMPLE
  448. Update-Database -TargetMigration Second
  449. # Update database to a migration named "Second"
  450. # This will apply migrations if the target hasn't been applied or roll back migrations
  451. # if it has
  452. .EXAMPLE
  453. Update-Database -Script
  454. # Generate a script to update the database from it's current state to the latest migration
  455. .EXAMPLE
  456. Update-Database -Script -SourceMigration Second -TargetMigration First
  457. # Generate a script to migrate the database from a specified start migration
  458. # named "Second" to a specified target migration named "First"
  459. .EXAMPLE
  460. Update-Database -Script -SourceMigration $InitialDatabase
  461. # Generate a script that can upgrade a database currently at any version to the latest version.
  462. # The generated script includes logic to check the __MigrationsHistory table and only apply changes
  463. # that haven't been previously applied.
  464. .EXAMPLE
  465. Update-Database -TargetMigration $InitialDatabase
  466. # Runs the Down method to roll-back any migrations that have been applied to the database
  467. #>
  468. function Update-Database
  469. {
  470. [CmdletBinding(DefaultParameterSetName = 'ConnectionStringName')]
  471. param (
  472. [string] $SourceMigration,
  473. [string] $TargetMigration,
  474. [switch] $Script,
  475. [switch] $Force,
  476. [string] $ProjectName,
  477. [string] $StartUpProjectName,
  478. [string] $ConfigurationTypeName,
  479. [parameter(ParameterSetName = 'ConnectionStringName')]
  480. [string] $ConnectionStringName,
  481. [parameter(ParameterSetName = 'ConnectionStringAndProviderName',
  482. Mandatory = $true)]
  483. [string] $ConnectionString,
  484. [parameter(ParameterSetName = 'ConnectionStringAndProviderName',
  485. Mandatory = $true)]
  486. [string] $ConnectionProviderName,
  487. [string] $AppDomainBaseDirectory)
  488. Hint-Downgrade $MyInvocation.MyCommand
  489. $runner = New-MigrationsRunner $ProjectName $StartUpProjectName $null $ConfigurationTypeName $ConnectionStringName $ConnectionString $ConnectionProviderName $null $AppDomainBaseDirectory
  490. try
  491. {
  492. Invoke-RunnerCommand $runner System.Data.Entity.Migrations.UpdateDatabaseCommand @( $SourceMigration, $TargetMigration, $Script.IsPresent, $Force.IsPresent, $Verbose.IsPresent )
  493. $error = Get-RunnerError $runner
  494. if ($error)
  495. {
  496. if ($knownExceptions -notcontains $error.TypeName)
  497. {
  498. Write-Host $error.StackTrace
  499. }
  500. else
  501. {
  502. Write-Verbose $error.StackTrace
  503. }
  504. throw $error.Message
  505. }
  506. $(Get-VSComponentModel).GetService([NuGetConsole.IPowerConsoleWindow]).Show()
  507. }
  508. finally
  509. {
  510. Remove-Runner $runner
  511. }
  512. }
  513. <#
  514. .SYNOPSIS
  515. Displays the migrations that have been applied to the target database.
  516. .DESCRIPTION
  517. Displays the migrations that have been applied to the target database.
  518. .PARAMETER ProjectName
  519. Specifies the project that contains the migration configuration type to be
  520. used. If omitted, the default project selected in package manager console
  521. is used.
  522. .PARAMETER StartUpProjectName
  523. Specifies the configuration file to use for named connection strings. If
  524. omitted, the specified project's configuration file is used.
  525. .PARAMETER ConfigurationTypeName
  526. Specifies the migrations configuration to use. If omitted, migrations will
  527. attempt to locate a single migrations configuration type in the target
  528. project.
  529. .PARAMETER ConnectionStringName
  530. Specifies the name of a connection string to use from the application's
  531. configuration file.
  532. .PARAMETER ConnectionString
  533. Specifies the the connection string to use. If omitted, the context's
  534. default connection will be used.
  535. .PARAMETER ConnectionProviderName
  536. Specifies the provider invariant name of the connection string.
  537. .PARAMETER AppDomainBaseDirectory
  538. Specifies the directory to use for the app-domain that is used for running Migrations
  539. code such that the app-domain is able to find all required assemblies. This is an
  540. advanced option that should only be needed if the solution contains several projects
  541. such that the assemblies needed for the context and configuration are not all
  542. referenced from either the project containing the context or the project containing
  543. the migrations.
  544. #>
  545. function Get-Migrations
  546. {
  547. [CmdletBinding(DefaultParameterSetName = 'ConnectionStringName')]
  548. param (
  549. [string] $ProjectName,
  550. [string] $StartUpProjectName,
  551. [string] $ConfigurationTypeName,
  552. [parameter(ParameterSetName = 'ConnectionStringName')]
  553. [string] $ConnectionStringName,
  554. [parameter(ParameterSetName = 'ConnectionStringAndProviderName',
  555. Mandatory = $true)]
  556. [string] $ConnectionString,
  557. [parameter(ParameterSetName = 'ConnectionStringAndProviderName',
  558. Mandatory = $true)]
  559. [string] $ConnectionProviderName,
  560. [string] $AppDomainBaseDirectory)
  561. $runner = New-MigrationsRunner $ProjectName $StartUpProjectName $null $ConfigurationTypeName $ConnectionStringName $ConnectionString $ConnectionProviderName $null $AppDomainBaseDirectory
  562. try
  563. {
  564. Invoke-RunnerCommand $runner System.Data.Entity.Migrations.GetMigrationsCommand
  565. $error = Get-RunnerError $runner
  566. if ($error)
  567. {
  568. if ($knownExceptions -notcontains $error.TypeName)
  569. {
  570. Write-Host $error.StackTrace
  571. }
  572. else
  573. {
  574. Write-Verbose $error.StackTrace
  575. }
  576. throw $error.Message
  577. }
  578. }
  579. finally
  580. {
  581. Remove-Runner $runner
  582. }
  583. }
  584. function New-MigrationsRunner($ProjectName, $StartUpProjectName, $ContextProjectName, $ConfigurationTypeName, $ConnectionStringName, $ConnectionString, $ConnectionProviderName, $ContextAssemblyName, $AppDomainBaseDirectory)
  585. {
  586. $startUpProject = Get-MigrationsStartUpProject $StartUpProjectName $ProjectName
  587. Build-Project $startUpProject
  588. $project = Get-MigrationsProject $ProjectName
  589. Build-Project $project
  590. $contextProject = $project
  591. if ($ContextProjectName)
  592. {
  593. $contextProject = Get-SingleProject $ContextProjectName
  594. Build-Project $contextProject
  595. }
  596. $installPath = Get-EntityFrameworkInstallPath $project
  597. $toolsPath = Join-Path $installPath tools
  598. $info = New-AppDomainSetup $project $installPath
  599. $domain = [AppDomain]::CreateDomain('Migrations', $null, $info)
  600. $domain.SetData('project', $project)
  601. $domain.SetData('contextProject', $contextProject)
  602. $domain.SetData('startUpProject', $startUpProject)
  603. $domain.SetData('configurationTypeName', $ConfigurationTypeName)
  604. $domain.SetData('connectionStringName', $ConnectionStringName)
  605. $domain.SetData('connectionString', $ConnectionString)
  606. $domain.SetData('connectionProviderName', $ConnectionProviderName)
  607. $domain.SetData('contextAssemblyName', $ContextAssemblyName)
  608. $domain.SetData('appDomainBaseDirectory', $AppDomainBaseDirectory)
  609. $dispatcher = New-DomainDispatcher $toolsPath
  610. $domain.SetData('efDispatcher', $dispatcher)
  611. return @{
  612. Domain = $domain;
  613. ToolsPath = $toolsPath
  614. }
  615. }
  616. function New-EFConfigRunner($Project)
  617. {
  618. $installPath = Get-EntityFrameworkInstallPath $Project
  619. $toolsPath = Join-Path $installPath tools
  620. $info = New-AppDomainSetup $Project $installPath
  621. $domain = [AppDomain]::CreateDomain('EFConfig', $null, $info)
  622. $domain.SetData('project', $Project)
  623. $dispatcher = New-DomainDispatcher $toolsPath
  624. $domain.SetData('efDispatcher', $dispatcher)
  625. return @{
  626. Domain = $domain;
  627. ToolsPath = $toolsPath
  628. }
  629. }
  630. function New-AppDomainSetup($Project, $InstallPath)
  631. {
  632. $info = New-Object System.AppDomainSetup -Property @{
  633. ShadowCopyFiles = 'true';
  634. ApplicationBase = $InstallPath;
  635. PrivateBinPath = 'tools';
  636. ConfigurationFile = ([AppDomain]::CurrentDomain.SetupInformation.ConfigurationFile)
  637. }
  638. $targetFrameworkVersion = (New-Object System.Runtime.Versioning.FrameworkName ($Project.Properties.Item('TargetFrameworkMoniker').Value)).Version
  639. if ($targetFrameworkVersion -lt (New-Object Version @( 4, 5 )))
  640. {
  641. $info.PrivateBinPath += ';lib\net40'
  642. }
  643. else
  644. {
  645. $info.PrivateBinPath += ';lib\net45'
  646. }
  647. return $info
  648. }
  649. function New-DomainDispatcher($ToolsPath)
  650. {
  651. $utilityAssembly = [System.Reflection.Assembly]::LoadFrom((Join-Path $ToolsPath EntityFramework.PowerShell.Utility.dll))
  652. $dispatcher = $utilityAssembly.CreateInstance(
  653. 'System.Data.Entity.Migrations.Utilities.DomainDispatcher',
  654. $false,
  655. [System.Reflection.BindingFlags]::Instance -bor [System.Reflection.BindingFlags]::Public,
  656. $null,
  657. $PSCmdlet,
  658. $null,
  659. $null)
  660. return $dispatcher
  661. }
  662. function Remove-Runner($runner)
  663. {
  664. [AppDomain]::Unload($runner.Domain)
  665. }
  666. function Invoke-RunnerCommand($runner, $command, $parameters, $anonymousArguments)
  667. {
  668. $domain = $runner.Domain
  669. if ($anonymousArguments)
  670. {
  671. $anonymousArguments.GetEnumerator() | %{
  672. $domain.SetData($_.Name, $_.Value)
  673. }
  674. }
  675. $domain.CreateInstanceFrom(
  676. (Join-Path $runner.ToolsPath EntityFramework.PowerShell.dll),
  677. $command,
  678. $false,
  679. 0,
  680. $null,
  681. $parameters,
  682. $null,
  683. $null) | Out-Null
  684. }
  685. function Get-RunnerError($runner)
  686. {
  687. $domain = $runner.Domain
  688. if (!$domain.GetData('wasError'))
  689. {
  690. return $null
  691. }
  692. return @{
  693. Message = $domain.GetData('error.Message');
  694. TypeName = $domain.GetData('error.TypeName');
  695. StackTrace = $domain.GetData('error.StackTrace')
  696. }
  697. }
  698. function Get-MigrationsProject($name, $hideMessage)
  699. {
  700. if ($name)
  701. {
  702. return Get-SingleProject $name
  703. }
  704. $project = Get-Project
  705. $projectName = $project.Name
  706. if (!$hideMessage)
  707. {
  708. Write-Verbose "Using NuGet project '$projectName'."
  709. }
  710. return $project
  711. }
  712. function Get-MigrationsStartUpProject($name, $fallbackName)
  713. {
  714. $startUpProject = $null
  715. if ($name)
  716. {
  717. $startUpProject = Get-SingleProject $name
  718. }
  719. else
  720. {
  721. $startupProjectPaths = $DTE.Solution.SolutionBuild.StartupProjects
  722. if ($startupProjectPaths)
  723. {
  724. if ($startupProjectPaths.Length -eq 1)
  725. {
  726. $startupProjectPath = $startupProjectPaths[0]
  727. if (!(Split-Path -IsAbsolute $startupProjectPath))
  728. {
  729. $solutionPath = Split-Path $DTE.Solution.Properties.Item('Path').Value
  730. $startupProjectPath = Join-Path $solutionPath $startupProjectPath -Resolve
  731. }
  732. $startupProject = Get-SolutionProjects | ?{
  733. try
  734. {
  735. $fullName = $_.FullName
  736. }
  737. catch [NotImplementedException]
  738. {
  739. return $false
  740. }
  741. if ($fullName -and $fullName.EndsWith('\'))
  742. {
  743. $fullName = $fullName.Substring(0, $fullName.Length - 1)
  744. }
  745. return $fullName -eq $startupProjectPath
  746. }
  747. }
  748. else
  749. {
  750. Write-Verbose 'More than one start-up project found.'
  751. }
  752. }
  753. else
  754. {
  755. Write-Verbose 'No start-up project found.'
  756. }
  757. }
  758. if (!($startUpProject -and (Test-StartUpProject $startUpProject)))
  759. {
  760. $startUpProject = Get-MigrationsProject $fallbackName $true
  761. $startUpProjectName = $startUpProject.Name
  762. 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."
  763. }
  764. else
  765. {
  766. $startUpProjectName = $startUpProject.Name
  767. Write-Verbose "Using StartUp project '$startUpProjectName'."
  768. }
  769. return $startUpProject
  770. }
  771. function Get-SolutionProjects()
  772. {
  773. $projects = New-Object System.Collections.Stack
  774. $DTE.Solution.Projects | %{
  775. $projects.Push($_)
  776. }
  777. while ($projects.Count -ne 0)
  778. {
  779. $project = $projects.Pop();
  780. # NOTE: This line is similar to doing a "yield return" in C#
  781. $project
  782. if ($project.ProjectItems)
  783. {
  784. $project.ProjectItems | ?{ $_.SubProject } | %{
  785. $projects.Push($_.SubProject)
  786. }
  787. }
  788. }
  789. }
  790. function Get-SingleProject($name)
  791. {
  792. $project = Get-Project $name
  793. if ($project -is [array])
  794. {
  795. throw "More than one project '$name' was found. Specify the full name of the one to use."
  796. }
  797. return $project
  798. }
  799. function Test-StartUpProject($project)
  800. {
  801. if ($project.Kind -eq '{cc5fd16d-436d-48ad-a40c-5a424c6e3e79}')
  802. {
  803. $projectName = $project.Name
  804. Write-Verbose "Cannot use start-up project '$projectName'. The Windows Azure Project type isn't supported."
  805. return $false
  806. }
  807. return $true
  808. }
  809. function Build-Project($project)
  810. {
  811. $configuration = $DTE.Solution.SolutionBuild.ActiveConfiguration.Name
  812. $DTE.Solution.SolutionBuild.BuildProject($configuration, $project.UniqueName, $true)
  813. if ($DTE.Solution.SolutionBuild.LastBuildInfo)
  814. {
  815. $projectName = $project.Name
  816. throw "The project '$projectName' failed to build."
  817. }
  818. }
  819. function Get-EntityFrameworkInstallPath($project)
  820. {
  821. $package = Get-Package -ProjectName $project.FullName | ?{ $_.Id -eq 'EntityFramework' }
  822. if (!$package)
  823. {
  824. $projectName = $project.Name
  825. throw "The EntityFramework package is not installed on project '$projectName'."
  826. }
  827. return Get-PackageInstallPath $package
  828. }
  829. function Get-PackageInstallPath($package)
  830. {
  831. $componentModel = Get-VsComponentModel
  832. $packageInstallerServices = $componentModel.GetService([NuGet.VisualStudio.IVsPackageInstallerServices])
  833. $vsPackage = $packageInstallerServices.GetInstalledPackages() | ?{ $_.Id -eq $package.Id -and $_.Version -eq $package.Version }
  834. return $vsPackage.InstallPath
  835. }
  836. function Check-Project($project)
  837. {
  838. if (!$project.FullName)
  839. {
  840. throw "The Project argument must refer to a Visual Studio project. Use the '`$project' variable provided by NuGet when running in install.ps1."
  841. }
  842. return $project.CodeModel
  843. }
  844. function Hint-Downgrade ($name) {
  845. if (Get-Module | Where { $_.Name -eq 'EntityFrameworkCore' }) {
  846. Write-Warning "Both Entity Framework 6.x and Entity Framework Core commands are installed. The Entity Framework 6 version is executing. You can fully qualify the command to select which one to execute, 'EntityFramework\$name' for EF6.x and 'EntityFrameworkCore\$name' for EF Core."
  847. }
  848. }
  849. Export-ModuleMember @( 'Enable-Migrations', 'Add-Migration', 'Update-Database', 'Get-Migrations', 'Add-EFProvider', 'Add-EFDefaultConnectionFactory', 'Initialize-EFConfiguration') -Variable InitialDatabase
  850. # SIG # Begin signature block
  851. # MIIa3gYJKoZIhvcNAQcCoIIazzCCGssCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
  852. # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
  853. # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUMst5oGNhRFW5FyGr05jAUKeC
  854. # HF6gghWAMIIEwjCCA6qgAwIBAgITMwAAAL+RbPt8GiTgIgAAAAAAvzANBgkqhkiG
  855. # 9w0BAQUFADB3MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4G
  856. # A1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSEw
  857. # HwYDVQQDExhNaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EwHhcNMTYwOTA3MTc1ODQ5
  858. # WhcNMTgwOTA3MTc1ODQ5WjCBsjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hp
  859. # bmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jw
  860. # b3JhdGlvbjEMMAoGA1UECxMDQU9DMScwJQYDVQQLEx5uQ2lwaGVyIERTRSBFU046
  861. # NTdDOC0yRDE1LTFDOEIxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNl
  862. # cnZpY2UwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCt7X+GwPaidVcV
  863. # TRT2yohV/L1dpTMCvf4DHlCY0GUmhEzD4Yn22q/qnqZTHDd8IlI/OHvKhWC9ksKE
  864. # F+BgBHtUQPSg7s6+ZXy69qX64r6m7X/NYizeK31DsScLsDHnqsbnwJaNZ2C2u5hh
  865. # cKsHvc8BaSsv/nKlr6+eg2iX2y9ai1uB1ySNeunEtdfchAr1U6Qb7AJHrXMTdKl8
  866. # ptLov67aFU0rRRMwQJOWHR+o/gQa9v4z/f43RY2PnMRoF7Dztn6ditoQ9CgTiMdS
  867. # MtsqFWMAQNMt5bZ8oY1hmgkSDN6FwTjVyUEE6t3KJtgX2hMHjOVqtHXQlud0GR3Z
  868. # LtAOMbS7AgMBAAGjggEJMIIBBTAdBgNVHQ4EFgQU5GwaORrHk1i0RjZlB8QAt3kX
  869. # nBEwHwYDVR0jBBgwFoAUIzT42VJGcArtQPt2+7MrsMM1sw8wVAYDVR0fBE0wSzBJ
  870. # oEegRYZDaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMv
  871. # TWljcm9zb2Z0VGltZVN0YW1wUENBLmNybDBYBggrBgEFBQcBAQRMMEowSAYIKwYB
  872. # BQUHMAKGPGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljcm9z
  873. # b2Z0VGltZVN0YW1wUENBLmNydDATBgNVHSUEDDAKBggrBgEFBQcDCDANBgkqhkiG
  874. # 9w0BAQUFAAOCAQEAjt62jcZ+2YBqm7RKit827DRU9OKioi6HEERT0X0bL+JjUTu3
  875. # 7k4piPcK3J/0cfktWuPjrYSuySa/NbkmlvAhQV4VpoWxipx3cZplF9HK9IH4t8AD
  876. # YDxUI5u1xb2r24aExGIzWY+1uH92bzTKbAjuwNzTMQ1z10Kca4XXPI4HFZalXxgL
  877. # fbjCkV3IKNspU1TILV0Dzk0tdKAwx/MoeZN1HFcB9WjzbpFnCVH+Oy/NyeJOyiNE
  878. # 4uT/6iyHz1+XCqf2nIrV/DXXsJYKwifVlOvSJ4ZrV40MYucq3lWQuKERfXivLFXl
  879. # dKyXQrS4eeToRPSevRisc0GBYuZczpkdeN5faDCCBOswggPToAMCAQICEzMAAAF4
  880. # JVq1zSPGX5UAAQAAAXgwDQYJKoZIhvcNAQEFBQAweTELMAkGA1UEBhMCVVMxEzAR
  881. # BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1p
  882. # Y3Jvc29mdCBDb3Jwb3JhdGlvbjEjMCEGA1UEAxMaTWljcm9zb2Z0IENvZGUgU2ln
  883. # bmluZyBQQ0EwHhcNMTcwODExMjAxMTE1WhcNMTgwODExMjAxMTE1WjCBgjELMAkG
  884. # A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx
  885. # HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEMMAoGA1UECxMDQU9DMR4w
  886. # HAYDVQQDExVNaWNyb3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUA
  887. # A4IBDwAwggEKAoIBAQCZbh1TVaudsrIbXUPPB9c8S+E+dKSbskHKYlG6SGTH8jhT
  888. # hpuvGiAO87F2b9GHVN+DvszaMkGy/xQgHaGEJLfpnb3kpakic7E0bjDHdG4KnHRb
  889. # no/wfUkGLfS79o+cw//RY8Ck6yE+0czDBcxp0Gbw5JyGP+KFqvzRR/3Tv3nt/5x0
  890. # 5ZnEOHYP+eDVikDvn/DH+oxxtiCfX3tkvtm/yX4eOb47YdmYKQjCgz2+Nil/lupY
  891. # vU0QFIjvke3jshqQINDng/vO9ys2qA0ex/q5hlLKQTST99dGoM86Ge6F723ReToq
  892. # KnGLN8kiCG7uNapOAIQrpCHZq96CVumiaA5ZvxU9AgMBAAGjggFgMIIBXDATBgNV
  893. # HSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUjuhtD3FD7tk/RKloJFX05cpgLjcw
  894. # UQYDVR0RBEowSKRGMEQxDDAKBgNVBAsTA0FPQzE0MDIGA1UEBRMrMjI5ODAzKzFh
  895. # YmY5ZTVmLWNlZDAtNDJlNi1hNjVkLWQ5MzUwOTU5ZmUwZTAfBgNVHSMEGDAWgBTL
  896. # EejK0rQWWAHJNy4zFha5TJoKHzBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3Js
  897. # Lm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNDb2RTaWdQQ0FfMDgt
  898. # MzEtMjAxMC5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8v
  899. # d3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY0NvZFNpZ1BDQV8wOC0zMS0y
  900. # MDEwLmNydDANBgkqhkiG9w0BAQUFAAOCAQEAYnG/oHG/xgZYR8NAMHZ/vE9GM0e4
  901. # 7YdhuTea2uY7pSGwM707wp8Wan0Fa6evK1PWfcd/XNOh2BpEv5o8RmKDoEsG0ECP
  902. # 13Jug7cklfKreBVHQ+Djg43VVFLZpuo7aOAVK6wjlcnpPUtn+SfH9K0aM2FjDKVJ
  903. # FW6XFKXBat5R+Zp6uOxWTxpSeMTeDC5zF6IY6ogR1uzU+9EQoRlAvkwX6po+exEL
  904. # nMLr4++P+fqOxIU+PODIoB8ijClAqwwKvLlMPa3qlrNHt+LweTMu7lvGC/RA18wU
  905. # zzXAeomuZ03blUw+bkOiVgWOk4S0RN7EnW7zjJV8gd/+G2dbToUi1cB/fTCCBbww
  906. # ggOkoAMCAQICCmEzJhoAAAAAADEwDQYJKoZIhvcNAQEFBQAwXzETMBEGCgmSJomT
  907. # 8ixkARkWA2NvbTEZMBcGCgmSJomT8ixkARkWCW1pY3Jvc29mdDEtMCsGA1UEAxMk
  908. # TWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTEwMDgzMTIy
  909. # MTkzMloXDTIwMDgzMTIyMjkzMloweTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh
  910. # c2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBD
  911. # b3Jwb3JhdGlvbjEjMCEGA1UEAxMaTWljcm9zb2Z0IENvZGUgU2lnbmluZyBQQ0Ew
  912. # ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCycllcGTBkvx2aYCAgQpl2
  913. # U2w+G9ZvzMvx6mv+lxYQ4N86dIMaty+gMuz/3sJCTiPVcgDbNVcKicquIEn08Gis
  914. # TUuNpb15S3GbRwfa/SXfnXWIz6pzRH/XgdvzvfI2pMlcRdyvrT3gKGiXGqelcnNW
  915. # 8ReU5P01lHKg1nZfHndFg4U4FtBzWwW6Z1KNpbJpL9oZC/6SdCnidi9U3RQwWfjS
  916. # jWL9y8lfRjFQuScT5EAwz3IpECgixzdOPaAyPZDNoTgGhVxOVoIoKgUyt0vXT2Pn
  917. # 0i1i8UU956wIAPZGoZ7RW4wmU+h6qkryRs83PDietHdcpReejcsRj1Y8wawJXwPT
  918. # AgMBAAGjggFeMIIBWjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTLEejK0rQW
  919. # WAHJNy4zFha5TJoKHzALBgNVHQ8EBAMCAYYwEgYJKwYBBAGCNxUBBAUCAwEAATAj
  920. # BgkrBgEEAYI3FQIEFgQU/dExTtMmipXhmGA7qDFvpjy82C0wGQYJKwYBBAGCNxQC
  921. # BAweCgBTAHUAYgBDAEEwHwYDVR0jBBgwFoAUDqyCYEBWJ5flJRP8KuEKU5VZ5KQw
  922. # UAYDVR0fBEkwRzBFoEOgQYY/aHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraS9j
  923. # cmwvcHJvZHVjdHMvbWljcm9zb2Z0cm9vdGNlcnQuY3JsMFQGCCsGAQUFBwEBBEgw
  924. # RjBEBggrBgEFBQcwAoY4aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0
  925. # cy9NaWNyb3NvZnRSb290Q2VydC5jcnQwDQYJKoZIhvcNAQEFBQADggIBAFk5Pn8m
  926. # Rq/rb0CxMrVq6w4vbqhJ9+tfde1MOy3XQ60L/svpLTGjI8x8UJiAIV2sPS9MuqKo
  927. # VpzjcLu4tPh5tUly9z7qQX/K4QwXaculnCAt+gtQxFbNLeNK0rxw56gNogOlVuC4
  928. # iktX8pVCnPHz7+7jhh80PLhWmvBTI4UqpIIck+KUBx3y4k74jKHK6BOlkU7IG9KP
  929. # cpUqcW2bGvgc8FPWZ8wi/1wdzaKMvSeyeWNWRKJRzfnpo1hW3ZsCRUQvX/TartSC
  930. # Mm78pJUT5Otp56miLL7IKxAOZY6Z2/Wi+hImCWU4lPF6H0q70eFW6NB4lhhcyTUW
  931. # X92THUmOLb6tNEQc7hAVGgBd3TVbIc6YxwnuhQ6MT20OE049fClInHLR82zKwexw
  932. # o1eSV32UjaAbSANa98+jZwp0pTbtLS8XyOZyNxL0b7E8Z4L5UrKNMxZlHg6K3RDe
  933. # ZPRvzkbU0xfpecQEtNP7LN8fip6sCvsTJ0Ct5PnhqX9GuwdgR2VgQE6wQuxO7bN2
  934. # edgKNAltHIAxH+IOVN3lofvlRxCtZJj/UBYufL8FIXrilUEnacOTj5XJjdibIa4N
  935. # XJzwoq6GaIMMai27dmsAHZat8hZ79haDJLmIz2qoRzEvmtzjcT3XAH5iR9HOiMm4
  936. # GPoOco3Boz2vAkBq/2mbluIQqBC0N1AI1sM9MIIGBzCCA++gAwIBAgIKYRZoNAAA
  937. # AAAAHDANBgkqhkiG9w0BAQUFADBfMRMwEQYKCZImiZPyLGQBGRYDY29tMRkwFwYK
  938. # CZImiZPyLGQBGRYJbWljcm9zb2Z0MS0wKwYDVQQDEyRNaWNyb3NvZnQgUm9vdCBD
  939. # ZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDcwNDAzMTI1MzA5WhcNMjEwNDAzMTMw
  940. # MzA5WjB3MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE
  941. # BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSEwHwYD
  942. # VQQDExhNaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EwggEiMA0GCSqGSIb3DQEBAQUA
  943. # A4IBDwAwggEKAoIBAQCfoWyx39tIkip8ay4Z4b3i48WZUSNQrc7dGE4kD+7Rp9FM
  944. # rXQwIBHrB9VUlRVJlBtCkq6YXDAm2gBr6Hu97IkHD/cOBJjwicwfyzMkh53y9Gcc
  945. # LPx754gd6udOo6HBI1PKjfpFzwnQXq/QsEIEovmmbJNn1yjcRlOwhtDlKEYuJ6yG
  946. # T1VSDOQDLPtqkJAwbofzWTCd+n7Wl7PoIZd++NIT8wi3U21StEWQn0gASkdmEScp
  947. # ZqiX5NMGgUqi+YSnEUcUCYKfhO1VeP4Bmh1QCIUAEDBG7bfeI0a7xC1Un68eeEEx
  948. # d8yb3zuDk6FhArUdDbH895uyAc4iS1T/+QXDwiALAgMBAAGjggGrMIIBpzAPBgNV
  949. # HRMBAf8EBTADAQH/MB0GA1UdDgQWBBQjNPjZUkZwCu1A+3b7syuwwzWzDzALBgNV
  950. # HQ8EBAMCAYYwEAYJKwYBBAGCNxUBBAMCAQAwgZgGA1UdIwSBkDCBjYAUDqyCYEBW
  951. # J5flJRP8KuEKU5VZ5KShY6RhMF8xEzARBgoJkiaJk/IsZAEZFgNjb20xGTAXBgoJ
  952. # kiaJk/IsZAEZFgltaWNyb3NvZnQxLTArBgNVBAMTJE1pY3Jvc29mdCBSb290IENl
  953. # cnRpZmljYXRlIEF1dGhvcml0eYIQea0WoUqgpa1Mc1j0BxMuZTBQBgNVHR8ESTBH
  954. # MEWgQ6BBhj9odHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0
  955. # cy9taWNyb3NvZnRyb290Y2VydC5jcmwwVAYIKwYBBQUHAQEESDBGMEQGCCsGAQUF
  956. # BzAChjhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY3Jvc29m
  957. # dFJvb3RDZXJ0LmNydDATBgNVHSUEDDAKBggrBgEFBQcDCDANBgkqhkiG9w0BAQUF
  958. # AAOCAgEAEJeKw1wDRDbd6bStd9vOeVFNAbEudHFbbQwTq86+e4+4LtQSooxtYrhX
  959. # AstOIBNQmd16QOJXu69YmhzhHQGGrLt48ovQ7DsB7uK+jwoFyI1I4vBTFd1Pq5Lk
  960. # 541q1YDB5pTyBi+FA+mRKiQicPv2/OR4mS4N9wficLwYTp2OawpylbihOZxnLcVR
  961. # DupiXD8WmIsgP+IHGjL5zDFKdjE9K3ILyOpwPf+FChPfwgphjvDXuBfrTot/xTUr
  962. # XqO/67x9C0J71FNyIe4wyrt4ZVxbARcKFA7S2hSY9Ty5ZlizLS/n+YWGzFFW6J1w
  963. # lGysOUzU9nm/qhh6YinvopspNAZ3GmLJPR5tH4LwC8csu89Ds+X57H2146SodDW4
  964. # TsVxIxImdgs8UoxxWkZDFLyzs7BNZ8ifQv+AeSGAnhUwZuhCEl4ayJ4iIdBD6Svp
  965. # u/RIzCzU2DKATCYqSCRfWupW76bemZ3KOm+9gSd0BhHudiG/m4LBJ1S2sWo9iaF2
  966. # YbRuoROmv6pH8BJv/YoybLL+31HIjCPJZr2dHYcSZAI9La9Zj7jkIeW1sMpjtHhU
  967. # BdRBLlCslLCleKuzoJZ1GtmShxN1Ii8yqAhuoFuMJb+g74TKIdbrHk/Jmu5J4PcB
  968. # ZW+JC33Iacjmbuqnl84xKf8OxVtc2E0bodj6L54/LlUWa8kTo/0xggTIMIIExAIB
  969. # ATCBkDB5MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE
  970. # BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSMwIQYD
  971. # VQQDExpNaWNyb3NvZnQgQ29kZSBTaWduaW5nIFBDQQITMwAAAXglWrXNI8ZflQAB
  972. # AAABeDAJBgUrDgMCGgUAoIHhMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwG
  973. # CisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMCMGCSqGSIb3DQEJBDEWBBTlz9AL
  974. # f1sBglUb85Teir2bIYmVvDCBgAYKKwYBBAGCNwIBDDFyMHCgUoBQAEUAbgB0AGkA
  975. # dAB5ACAARgByAGEAbQBlAHcAbwByAGsAIABUAG8AbwBsAHMAIABmAG8AcgAgAFYA
  976. # aQBzAHUAYQBsACAAUwB0AHUAZABpAG+hGoAYaHR0cDovL21zZG4uY29tL2RhdGEv
  977. # ZWYgMA0GCSqGSIb3DQEBAQUABIIBAGeaKWq3ThdTiw0FniJGaIvelS5BghhhNI3x
  978. # ezUDCIPfp6Glc9zffEPt3qMdZORjY3mgsbrRO7hXNm9GR5cb68G5C7/LhrWfp34J
  979. # yWQ1dbnApNi6bp64SEML52vcDVMMHnbKRM3ns0/y/qu/XH2GSUUPuEjD7cd5t0NO
  980. # DUQZ2gHt4JeqZERgvNQWTxdUn83V2BwOz1i6KtHzmGdvEjb8ZrPQTlu1UoHHYXsQ
  981. # jUv8dhEHkaj3o2jLEIhYXp1ait0/OAk9dA5QdPVCBHy4RkDLWI4v58s0j1J0Cw0l
  982. # 2a/7+Agm1vvVLQZHofllOSIgd5Aj4Y1NiMYpLo8Y4z3iBRXgUQKhggIoMIICJAYJ
  983. # KoZIhvcNAQkGMYICFTCCAhECAQEwgY4wdzELMAkGA1UEBhMCVVMxEzARBgNVBAgT
  984. # Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m
  985. # dCBDb3Jwb3JhdGlvbjEhMB8GA1UEAxMYTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENB
  986. # AhMzAAAAv5Fs+3waJOAiAAAAAAC/MAkGBSsOAwIaBQCgXTAYBgkqhkiG9w0BCQMx
  987. # CwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0xNzEwMjMyMDEzNDhaMCMGCSqG
  988. # SIb3DQEJBDEWBBTDiJZ8a7P4Som1wzlUt7g8OiC3qzANBgkqhkiG9w0BAQUFAASC
  989. # AQAmJlbq0GKEk6SUOqA4Ksyj99KUlnPFcFyf1AqvHRdShmQjfEEo/pmR9cWmGNdA
  990. # 8M7wVFFZFRlmkF3oCl//ckniUJ/aDYtXCTskDFd2Tc8xJ/nsJOespt0LSpbiadxI
  991. # Goa9nZNXymAEidosoh0MmqB25gQfq9X+mMU7rVUp9eBUjAcoT3FHv+gkzE1XjvDE
  992. # YFGvQ1PRxjiYKlQKITDhtFhog2MSuGtvWpFV1aeqXDrANONlLyrscHrzKjQkKiwU
  993. # PPJQ+iygds9A3xUri6Jevj7Yjvr0hBTFaxL7xmQtgaafY/TqAtRcbCz2Gu9hkUay
  994. # WYGdtIZc7fAdNGkxqRxddvkD
  995. # SIG # End signature block