2

I'm trying to play around with EntityFramework6. I'm using a code first approach, and I've created a database in my projectfolder/bin/debug/SchoolContext.mdf. The database has the proper tables when created and I'm also capable of adding data to it.

I reached a point in the tutorial where I can use migration to update the field. So I enabled the migrations from package manager, removed a field from a table and generated the migration by using Add-Migration MigrationName. The migration is generated, but when I try to run it by using Update-Database, I get the following:

CREATE FILE encountered operating system error 5(Access is denied.) while attempting to open or create the physical file 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\SchoolContext.mdf'.

...

The problem is that it is looking for the mdf file in the wrong path. I've tried to find how to solve this, but I couldn't.

The right path would be: C:\Users\home\Documents\Visual Studio 2017\Projects\Test2\Test2\bin\Debug\SchoolContext.mdf

Here is my auto generated App.config file + my modifications of adding a connection string.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=bcsfdadsa56145" requirePermission="false" />
  </configSections>
  <connectionStrings>
    <add name="SchoolContext" connectionString="Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|SchoolContext.mdf;Integrated Security=True;Connect Timeout=30" providerName="System.Data.SqlClient" />
 </connectionStrings>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
  </startup>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="v11.0" />
      </parameters>
    </defaultConnectionFactory>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>
</configuration>

I do set the DataDirectory in the configuration file:

internal sealed class Configuration : DbMigrationsConfiguration<Test2.Data.SchoolContext>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = false;
        AppDomain.CurrentDomain.SetData("DataDirectory", System.IO.Directory.GetCurrentDirectory());
...
Bogdan Daniel
  • 2,689
  • 11
  • 43
  • 76
  • Are you sure that Configuration is istantiated? I'm asking it because of internal. Are you specifying it on `Database.SetInitializer`? – bubi Jul 06 '17 at 09:27
  • My experience with this whole migration and database in c# is limited. I don t recall using set initializer anywhere, but if I put a breakpoint in the configuration and I run the project it is stopped. – Bogdan Daniel Jul 06 '17 at 09:36
  • I think that the DataDirectory is not the right way. I don't know your requirements but you can also create a context specifying a connection or in several other ways. Check also this https://stackoverflow.com/questions/29440405/entity-framework-6-set-connection-string-runtime – bubi Jul 06 '17 at 09:41
  • @bubi you can take a look here https://github.com/iDaniel/WPFTest. I've tried few things so there aren't many files. – Bogdan Daniel Jul 06 '17 at 10:13

1 Answers1

1

Code First allows you to stop using file path based connection strings in favour of much simpler connection strings that use a database name:

<connectionStrings> 
    <add name="SchoolContext"  
         connectionString="Server=(LocalDB)\MSSQLLocalDB;Database=School;Integrated Security=True;Connect Timeout=30" 
         providerName="System.Data.SqlClient"  /> 
</connectionStrings>

You don't need to configure the path of the database, you just need the database name. You can remove the AppDomain.CurrentDomain.SetData() code from your Configuration class.

A simple way to make sure that the right connection string is used by your application runtime and also at design time by the Package Manager Console: your DbContext class should have a parameterless constructor that invokes the base constructor with the connection string name in your app.config file:

public MyDbContext() : base("SchoolContext") 
{ ... }

This is the easiest way to specify the connection data. EF 6 provides other ways to do it, as explained in this msdn reference page.

And where will your database file be stored? It doesn't really matter anymore. This page explains it. But be aware that LocalDB is not intended to be used in production systems, only in development environments.

Diana
  • 2,186
  • 1
  • 20
  • 31
  • Thanks for answering. I was specifying the file path so the database is saved within the app folder. With your configuration the file will be saved in `C:\Users\yourusername` and I don't want that. – Bogdan Daniel Jul 07 '17 at 08:55
  • I see your point. Then you can try setting your `LocalDB` default path to a different place than your user profile with the `SQLLocalDB`command tool. Note that this will change the path for every other project too, so it would be better to specify a folder out of your specific project, something like `C:\Users\home\Documents\Visual Studio 2017\Projects\Databases` (perhaps you don't want that). [This post](https://stackoverflow.com/questions/23150238/localdb-change-sql-server-default-location) contains the detailed explanation. – Diana Jul 14 '17 at 21:49
  • Another thing to try: when running `Update-Database` provide the specific connection string in the parameter `-ConnectionString`. I'm not sure that it would get the `|DataDirectory|` configuration, you may have to replace that part with the real path. – Diana Jul 14 '17 at 21:58