Search code examples
c#asp.netef-code-firststreamreader

How to access a .txt file outside of the web root when doing a 'database-update' command?


In a web based app, I need to access a .txt file that is saved outside of the web project (so a path to it (I believe?) isn't possible). The ultimate goal is to use the .txt file to seed a database.

I thought in the past I'd seen where it's possible to access a .txt file as if it's a class, something like this...

(a pic is worth 1k words)...

enter image description here

But, resourceName ends up null.

Is this possible? I don't want to do a hard coded full path to the file, as it will be different on other dev's work stations, etc. What is the best way to do this?

I've also tried...

const string resourceName = "~/SeedData/ZipCodeStates.txt";

and

const string resourceName = "SeedData/ZipCodeStates.txt";

Here's the stack trace...

   at System.IO.StreamReader..ctor(Stream stream, Encoding encoding, Boolean detectEncodingFromByteOrderMarks, Int32 bufferSize, Boolean leaveOpen)
   at System.IO.StreamReader..ctor(Stream stream)
   at xxxxxEventLink.Data.Migrations.Configuration.AddOrUpdateZipCodeStates(IReadOnlyCollection`1 dbZipCodeStates) in C:\TFS\Workspaces\EventLink\xxxxx\xxxxxEventLink\Web\Main\xxxxxEventLink.Data\Migrations\Configuration.cs:line 57
   at xxxxxEventLink.Data.Migrations.Configuration.Seed(ApplicationDbContext context) in C:\TFS\Workspaces\EventLink\xxxxx\xxxxxEventLink\Web\Main\xxxxxEventLink.Data\Migrations\Configuration.cs:line 44
   at System.Data.Entity.Migrations.DbMigrationsConfiguration`1.OnSeed(DbContext context)
   at System.Data.Entity.Migrations.DbMigrator.SeedDatabase()
   at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.SeedDatabase()
   at System.Data.Entity.Migrations.DbMigrator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
   at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
   at System.Data.Entity.Migrations.DbMigrator.UpdateInternal(String targetMigration)
   at System.Data.Entity.Migrations.DbMigrator.<>c__DisplayClassc.<Update>b__b()
   at System.Data.Entity.Migrations.DbMigrator.EnsureDatabaseExists(Action mustSucceedToKeepDatabase)
   at System.Data.Entity.Migrations.Infrastructure.MigratorBase.EnsureDatabaseExists(Action mustSucceedToKeepDatabase)
   at System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration)
   at System.Data.Entity.Migrations.Infrastructure.MigratorBase.Update(String targetMigration)
   at System.Data.Entity.Migrations.Design.ToolingFacade.UpdateRunner.Run()
   at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
   at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
   at System.Data.Entity.Migrations.Design.ToolingFacade.Run(BaseRunner runner)
   at System.Data.Entity.Migrations.Design.ToolingFacade.Update(String targetMigration, Boolean force)
   at System.Data.Entity.Migrations.UpdateDatabaseCommand.<>c__DisplayClass2.<.ctor>b__0()
   at System.Data.Entity.Migrations.MigrationsDomainCommand.Execute(Action command)

Solution

  • You have a few options, you can:

    • Use a relative path from the current assemblies location: Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), @"..\..\Etc");
      If doing this, it may also be a good idea to set the text file to be copied to the output directory so you don't need to climb up through the bin directories.
    • Embed the text file as an embedded resource. Right click the file and set the build action to Embedded Resource, and then you can access it via: Assembly.GetExecutingAssembly().GetManifestResourceStream("...")
      If you don't know what to put in the ... part, you can check by looking at the result of: Assembly.GetExecutingAssembly().GetManifestResourceNames();