12

コンソール アプリケーションに次の C# コードがあります。

アプリケーションをデバッグし、(データベースに新しい値を挿入する) query1 を実行してから、(データベース内のすべてのエントリを表示する) query2 を実行すると、挿入した新しいエントリが明確に表示されます。ただし、アプリケーションを閉じてデータベース (Visual Studio) のテーブルを確認すると、消えてしまいます。保存しない理由がわかりません。

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.SqlServerCe;
using System.Data;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                string fileName = "FlowerShop.sdf";
                string fileLocation = "|DataDirectory|\\";
                DatabaseAccess dbAccess = new DatabaseAccess();
                dbAccess.Connect(fileName, fileLocation);

                Console.WriteLine("Connected to the following database:\n"+fileLocation + fileName+"\n");
                string query = "Insert into Products(Name, UnitPrice, UnitsInStock) values('NewItem', 500, 90)";
                string res = dbAccess.ExecuteQuery(query);
                Console.WriteLine(res);

                string query2 = "Select * from Products";
                string res2 = dbAccess.QueryData(query2);
                Console.WriteLine(res2);
                Console.ReadLine();
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                Console.ReadLine();
            }
        }
    }

    class DatabaseAccess
    {
        private SqlCeConnection _connection;

        public void Connect(string fileName, string fileLocation)
        {
            Connect(@"Data Source=" + fileLocation + fileName);
        }

        public void Connect(string connectionString)
        {
            _connection = new SqlCeConnection(connectionString);
        }

        public string QueryData(string query)
        {
            _connection.Open();
            using (SqlCeDataAdapter da = new SqlCeDataAdapter(query, _connection))
            using (DataSet ds = new DataSet("Data Set"))
            {
                da.Fill(ds);
                _connection.Close();
                return ds.Tables[0].ToReadableString(); // a extension method I created
            }
        }

        public string ExecuteQuery(string query)
        {
            _connection.Open();
            using (SqlCeCommand c = new SqlCeCommand(query, _connection))
            {
                int r = c.ExecuteNonQuery();
                _connection.Close();
                return r.ToString();
            }
        } 
    }

編集: SQL Server Compact Edition 4 と VS2012 Express を使用していることを忘れていました。

4

2 に答える 2

30

これは非常に一般的な問題です。|DataDirectory|を使用します。置換文字列。これは、Visual Studio 環境でアプリをデバッグしている間、アプリケーションで使用されるデータベースがプロジェクトのサブフォルダーBIN\DEBUGフォルダー (または x86 バリアント) にあることを意味します。データベースに接続して更新操作を行うときにエラーが発生しないため、これはうまく機能します。

ただし、デバッグ セッションを終了し、Visual Studio サーバー エクスプローラー (またはその他の適切なツール) を使用してデータベースを確認します。このウィンドウには、別の接続文字列があります (おそらく、プロジェクト フォルダー内のデータベースのコピーを指しています)。テーブルを検索しても、変更が表示されません。

その後、問題は悪化します。VS を再起動してアプリのバグを探しますが、プロジェクト ファイルの間にデータベース ファイルがリストされており、プロパティCopy to Output directoryが に設定されていCopy Alwaysます。この時点で、Visual Studio は元のデータベース ファイルをプロジェクト フォルダーから出力フォルダー (BIN\DEBUG) に強制してコピーするため、以前の変更は失われます。

ここで、アプリケーションはターゲット テーブルを再度挿入/更新します。また、コードにエラーが見つからず、StackOverflow で投稿または検索することを決定するまでループを再開できません。

Copy To Output Directoryソリューション エクスプローラーに一覧表示されているデータベース ファイルをクリックし、プロパティをCopy If Newerまたはに変更すると、この問題を回避できますNever Copy。また、サーバー エクスプローラーで接続文字列を更新して、データベースの作業コピーを確認したり、2 つ目の接続を作成したりすることもできます。最初のものは引き続きプロジェクト フォルダー内のデータベースを指し、2 番目のものは BIN\DEBUG フォルダー内のデータベースを指します。このようにして、元のデータベースを配置目的とスキーマ変更に備えた状態に保ちながら、2 番目の接続を使用して、コーディング作業の効果的な結果を確認できます。

EDIT MS-Accessデータベース ユーザー 向けの特別な警告。テーブルを見るという単純な行為は、何も書いたり変更したりしなければ、データベースの変更日も変更します。そのため、フラグCopy if Newerが開始され、データベース ファイルが出力ディレクトリにコピーされます。Access を使用すると、より効果的に使用できますCopy Never

于 2013-06-17T12:26:01.460 に答える
3

デバッグ セッション間での変更のコミット/変更の保存は、SQL CE フォーラムではおなじみのトピックです。それはかなりの人をつまずかせるものです。以下にソース記事へのリンクを掲載しますが、最も多くの人にとって最良の結果が得られると思われる回答を貼り付けたかったのです。


この動作を変更するには、いくつかのオプションがあります。SDF ファイルがプロジェクトのコンテンツの一部である場合、これはデータの保持方法に影響します。デバッグするときは、プロジェクトのすべての出力 (sdf を含む) が bin/debug フォルダーにあることに注意してください。

  • プロジェクトの一部として sdf ファイルを含めないことを決定し、ファイルの場所のランタイムを管理することができます。

  • 「新しい場合はコピー」を使用している場合、データベースに加えたプロジェクトの変更により、ランタイム/デバッグの変更が上書きされます。

  • 「コピーしない」を使用している場合は、コードで場所を指定する必要があります (プログラムが実行されている場所の 2 レベル上)。

  • 「常にコピー」を選択した場合、実行時に加えられた変更は常に上書きされます


回答元

これは、さらなる議論とドキュメントへの方法へのリンクです。

于 2013-06-17T12:28:31.913 に答える