筆者在使用Entity Framework中的Scaffolding機制自動建立拓展名爲mdf的數據庫及表單時,遇到以下的錯誤:數據庫
A file activation error occurred. The physical file name '\\MusicDBContext.mdf' may be incorrect. Diagnose and correct additional errors, and retry the operation. CREATE DATABASE failed. Some file names listed could not be created. Check related errors.
首先回顧一下建立這個程序的步驟:ide
一、建立一個Console控制檯應用程序,程序集名稱及命名空間爲ConsoleApp;this
二、使用程序包控制檯管理器將Entity Framework包含到此程序中,代碼以下:spa
PM> install-package Entity Framework
三、在App.Config文件中將如下內容插入到configuration節點:code
<connectionStrings> <add name="MusicDBContext" connectionString="Data Source=(LocalDb)\MSSQLLocalDB; Initial Catalog=MusicDBContext;Integrated Security=SSPI; AttachDBFilename=|DataDirectory|\MusicDBContext.mdf" providerName="System.Data.SqlClient" /> </connectionStrings>
四、在控制檯編寫如下代碼:orm
using System; using System.Linq; using System.Data.Entity; namespace ConsoleApp { class Program { static void Main(string[] args) { try { MusicDbContext db = new MusicDbContext(); Music music = new Music { Title = "Far Away From Home", ReleaseDate = DateTime.Now }; db.Musics.Add(music); db.SaveChanges(); db.Musics.ToList().ForEach(x => Console.WriteLine($"{x.ID}, {x.Title},{x.ReleaseDate}")); } catch (Exception ex) { Console.WriteLine(ex.Message); if(ex.InnerException != null) { Console.WriteLine(ex.InnerException.Message); } } Console.ReadKey(); } } public class Music { public int ID { get; set; } public string Title { get; set; } public DateTime ReleaseDate { set; get; } } public class MusicDbContext : DbContext { public MusicDbContext() : base("MusicDBContext") { } public DbSet<Music> Musics { set; get; } } }
五、運行此程序,發現程序不能按本身想要的結果運行,出如今最前面出現的錯誤。blog
經過查看出錯的信息,發現get
AttachDBFilename=|DataDirectory|\MusicDBContext.mdf
有問題,而這又是沒有問題的,這究竟是怎麼回事?爲何會出現錯誤?string
因而,經過MSDN查找相關資料,經過如下方法得到DataDirectory指定的路徑是什麼:it
object path = AppDomain.CurrentDomain.GetData("DataDirectory");
運行此行代碼,發現path竟然是null!!!什麼?通常控制檯或者Windows Form程序根據是Debug仍是Release決定DataDirectory的初始化路徑爲Bebug文件夾仍是Release文件夾嗎?
這個錯了。
若是原先的Bebug文件夾或Release文件夾存在數據庫文件,使用相似"AttachDBFilename=|DataDirectory|\MusicDBContext.mdf"的寫法是沒有問題的,
即便path = null,它也知道是在Bebug文件夾或Release文件夾下。
若是原先的Bebug文件夾或Release文件夾不存在數據庫文件,上面的寫法就有問題,也就會出現最開始出現的那種錯誤。
那麼,咱們該如何解決呢?細心的人能夠發現,既然可使用AppDomain.CurrentDomain.GetData來得到DataDirectory指定的路徑,
那及可使用AppDomain.CurrentDomain.SetData來指定DataDirectory的初始化路徑,代碼以下:
AppDomain.CurrentDomain.SetData("DataDirectory", Environment.CurrentDirectory);
經過以上的方法,就能夠解決最開始前面的問題。
經過以上的介紹,最終的代碼修改以下:
using System; using System.Linq; using System.IO; using System.Data.Entity; namespace ConsoleApp { class Program { static void Main(string[] args) { string dbPath = Environment.CurrentDirectory + @"\MusicDBContext.mdf"; if(!File.Exists(dbPath)) { AppDomain.CurrentDomain.SetData("DataDirectory", Environment.CurrentDirectory); } try { MusicDbContext db = new MusicDbContext(); Music music = new Music { Title = "Far Away From Home", ReleaseDate = DateTime.Now }; db.Musics.Add(music); db.SaveChanges(); db.Musics.ToList().ForEach(x => Console.WriteLine($"{x.ID},{x.Title},{x.ReleaseDate}")); } catch (Exception ex) { Console.WriteLine(ex.Message); if(ex.InnerException != null) { Console.WriteLine(ex.InnerException.Message); } } Console.ReadKey(); } } public class Music { public int ID { get; set; } public string Title { get; set; } public DateTime ReleaseDate { set; get; } } public class MusicDbContext : DbContext { public MusicDbContext() : base("MusicDBContext") { } public DbSet<Music> Musics { set; get; } } }
程序就能夠正常運行了。
注:
1)AttachDBFilename=|DataDirectory|\MusicDBContext.mdf
其中的「\」能夠省略掉,即爲:AttachDBFilename=|DataDirectory|MusicDBContext.mdf
2)若是是ASP.NET程序,DataDirectory的初始化目錄爲App_Data。
3)關於更多的|DataDirectory|知識,請參考以下:
https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/ef/connection-strings