SQLiteデータベースのファイルパスについて

Otake333 40 評価のポイント
2024-04-22T11:32:34.8133333+00:00

質問

  • データベースのファイルパスが期待と異なる理由について教えて下さい。

前提

  • .msix形式でパッケージした自作アプリ"HakkoQuiz"をインストールする。
  • Windows menu から自作アプリを起動する。
  • 自作アプリのクイズ開始ボタンを押下する。
  • ここでexception errorが発生する。

質問の意図

  • Windows menu から自作アプリを起動すると、database.db のファイルパスが期待と異なっていました。この理由がわからないため、教えて下さい。
    • 期待:"C:\Program Files\WindowsApps\Otake333.HakkoQuiz_1.0.0.0_x64__ad8pwfkyh69vj\VFS\ProgramFilesX86\HakkoSmile\HakkoQuiz\database.db"
    • 実際:"C:\WINDOWS\system32\database.db"
    • 参照:figure_all2.png

質問に至るまでの背景

  • Visual Studio から自作アプリにアタッチし、exception errorが発生する操作をした。
  • SQLiteConnectionインスタンスのOpen()メソッドを呼び出した後の内部処理をステップ実行し、差分を調べた。
  • _sql.Open() に渡しているパラメータ text3 が期待と異なっていた。
  • 自作アプリ「HakkoQuiz.WinForm.exe」 と データベース「database.db」がインストールされているパスは、同一フォルダであることを確認した。
  • 自分の書いたプログラムでは、 データベース「database.db」のパスを以下の通り指定していることを確認した。
    • ConnectionString = @"Data Source=database.db;Version=3;";
.NET
.NET
.NET ソフトウェア フレームワークに基づく Microsoft テクノロジ。
29 件の質問
0 件のコメント コメントはありません
{count} 件の投票

承認済みの回答
  1. gekka 6,666 評価のポイント MVP
    2024-04-23T00:37:18.89+00:00

    肝心のtext3をどのように得ているのかが書かれていないので推測ですが、System.Environment.CurrentDirectorySystem.IO.Directory.GetCurrentDirectoryをプログラムが配置されている場所として使用していませんか?
    MSIXでパッケージした既存アプリは、カレントディレクトリの初期値がシステムディレクトリになるので、これを使うと想定されていない場所になります。
    また、CurrentDirectoryは System.IO.Directory.SetCurrentDirectoryなどで変更されるので、固定された場所とはなりません。

    WindowsFormsを使っているなら、System.Windows.Forms.Application.StartupPathを使えばよいです。

    Console.WriteLine($"System.Environment.CurrentDirectory = {System.Environment.CurrentDirectory}");
    Console.WriteLine($"System.IO.Directory.GetCurrentDirectory = {System.IO.Directory.GetCurrentDirectory()}");
    
    Console.WriteLine($"System.Windows.Forms.Application.StartupPath = {System.Windows.Forms.Application.StartupPath}");
    
    Console.WriteLine($"typeof(Program).Assembly.Location = {System.IO.Path.GetDirectoryName(typeof(Program).Assembly.Location)}");
    Console.WriteLine($"System.Reflection.Assembly.GetExecutingAssemblye().Location = {System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)}");
    Console.WriteLine($"System.Reflection.Assembly.GetEntryAssembly().Location = {System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location)}");
    
    1 人がこの回答が役に立ったと思いました。

1 件の追加の回答

並べ替え方法: 最も役に立つ
  1. SurferOnWww 1,911 評価のポイント
    2024-04-23T01:33:57.96+00:00

    自作の Windows Forms アプリで接続文字列は質問者さんが自由に設定できるのですよね? であれば、接続文字列でのパスの指定

    ConnectionString = @"Data Source=database.db;Version=3;";

    を C: から始まるフルパス、すなわち以下のようにしたらどうなりますか?

    実際:"C:\WINDOWS\system32\database.db"

    もしくは、db ファイルを出力ディレクトリにコピーする設定にして、

    enter image description here

    プロジェクトをリビルドすれば出力ディレクトリ(bin フォルダ)にコピーが配置されるようになるので、その後であればファイル名だけで OK になるはずです。

    以下は SQLite を利用した .NET Framework 4.8 の Windows Forms アプリの記事ですが、

    DbProviderFactory の利用 http://surferonwww.info/BlogEngine/post/2023/07/04/use-of-dbproviderfactory.aspx

    上の画像のように db ファイル(上の例ではプロジェクトのフォルダに置いた Movie.db)を出力ディレクトリにコピーする設定にして、接続文字列を以下のようにし、

    <add name="ConnectionInfo"
         connectionString="Data Source=Movie.db"
         providerName="System.Data.SQLite"/>
    

    アプリを実行すれば db がアタッチされた SQLite に接続してデータを取得できています。

    enter image description here