質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Entity Framework

Entity Frameworkは、.NET Framework 3.5より追加されたデータアクセス技術。正式名称は「ADO.NET Entity Framework」です。データベースエンジンに依存しておらず、データプロバイダの変更のみで様々なデータベースに対応できます。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

SQLite

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

Q&A

解決済

1回答

2554閲覧

SQLite + Entity Framework: 省略した項目にテーブルで設定されたDefault値が入るようにしたい

sokafuji

総合スコア16

Entity Framework

Entity Frameworkは、.NET Framework 3.5より追加されたデータアクセス技術。正式名称は「ADO.NET Entity Framework」です。データベースエンジンに依存しておらず、データプロバイダの変更のみで様々なデータベースに対応できます。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

SQLite

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

0グッド

0クリップ

投稿2022/02/22 04:36

前提・実現したいこと

C#でEntity Frameworkを使用してSQLiteを操作するテストをしています。
値を省略した状態でINSERTした場合に、テーブルで設定されたDEFAULT値が入るようにしたいです。
また、最終的に各列にNOT NULL制約を掛けたいと思います。(下記コードでは掛けていません)

発生している問題

PRIMARY KEY に設定した AUTOINCREMENT は動作しますが、その他のDEFAULT値が反映されません。

例えば、次のような「何も設定していない」コードを何度か実行した場合に、

C#

1private void button1_Click(object sender, EventArgs e) 2{ 3 using (var db = new ClassDbConnection(Properties.Settings.Default.DbFile)) 4 { 5 var row = new ClassDbTFix(); 6 db.tFix.Add(row); 7 db.SaveChanges(); 8 } 9}

このような結果を期待していますが、

idcreated_atupdated_attestdata
12022/02/22 00:00:002022/02/22 00:00:0099
22022/02/22 00:00:012022/02/22 00:00:0199
32022/02/22 00:00:022022/02/22 00:00:0299

このようになります。

idcreated_atupdated_attestdata
1[NULL][NULL]0
2[NULL][NULL]0
3[NULL][NULL]0

たぶんマッピングに何か定義が足りないのだろうと思うのですが、回答を探せませんでした。

テーブルとトリガの定義

SQLiteで以下のようなテーブルを定義しました。

SQL

1CREATE TABLE t_fix ( 2 id INTEGER PRIMARY KEY AUTOINCREMENT, 3 created_at TEXT DEFAULT (DATETIME('now', 'localtime')), 4 updated_at TEXT DEFAULT (DATETIME('now', 'localtime')), 5 testdata INTEGER DEFAULT 99 6); 7 8CREATE TRIGGER trigger_fix_updated_at AFTER UPDATE ON t_fix 9BEGIN 10 UPDATE t_fix SET updated_at = DATETIME('now', 'localtime') WHERE rowid == NEW.rowid; 11END;

マッピング

以下のようにマッピングしています。

C#

1using System.ComponentModel.DataAnnotations; 2using System.ComponentModel.DataAnnotations.Schema; 3 4namespace Test 5{ 6 [Table("t_fix")] 7 internal class ClassDbTFix 8 { 9 // ID 10 [Key] 11 [Column("id")] 12 public long Id { get; set; } 13 // 登録日時 14 [Column("created_at")] 15 public DateTime CreatedAt { get; set; } 16 // 更新日時 17 [Column("updated_at")] 18 public DateTime UpdateAt { get; set; } 19 // テストデータ 20 [Column("testdata")] 21 public int TestData { get; set; } 22 } 23}

C#

1using Microsoft.Data.Sqlite; 2using Microsoft.EntityFrameworkCore; 3 4namespace Test 5{ 6 internal class ClassDbConnection : DbContext 7 { 8 /// <summary> 9 /// テーブル 10 /// </summary> 11 public DbSet<ClassDbTFix> tFix { get; set; } 12 13 private string DbFileName; 14 15 public ClassDbConnection(string fileName) 16 { 17 DbFileName = fileName; 18 } 19 20 protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) 21 { 22 var connectionString = new SqliteConnectionStringBuilder { DataSource = DbFileName }.ToString(); 23 optionsBuilder.UseSqlite(new SqliteConnection(connectionString)); 24 } 25 } 26}

環境

Visual Studio 2022 C#

NuGet Package:

  • System.Data.SQLite (v1.0.115.5)
  • Microsoft.Entity.FrameworkCore.Sqlite (v6.0.2)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2022/02/22 06:39 編集

先にここに書いたコメントは回答欄に移しました。
sokafuji

2022/02/22 06:22

なるほど、ということでマッピングを | public String CreatedAt { get; set; } | public String UpdateAt { get; set; } に変更して実行してみましたが、残念ながら結果は変わりませんでした。 created_atとupdated_atはSQLiteの定番のようなので、これを含んだEntity Frameworkの使用例が見付けられるといいのですが… 引き続き自分でも調べてみます、ありがとうございました。
退会済みユーザー

退会済みユーザー

2022/02/22 06:43

> なるほど、ということでマッピングを > | public String CreatedAt { get; set; } > | public String UpdateAt { get; set; } > に変更して実行してみましたが、残念ながら結果は変わりませんでした。 それは意味がなさそうですが? string は参照型なのでデフォルトは null になるはず。なので、INSERT 結果 SQLite 側が NULL になるのは当たり前のような気がします。
退会済みユーザー

退会済みユーザー

2022/02/22 06:46

> これを含んだEntity Frameworkの使用例が見付けられるといいのですが… 下の回答に書きましたが、SQLite 側にデフォルトの設定を期待せず、ClassDbTFix クラスのプロパティでデフォルト値が設定されるよう変更してはいかがですか?
guest

回答1

0

ベストアンサー

想像ですが・・・

var row = new ClassDbTFix(); で生成した ClassDbTFix オブジェクトの DateTime 型の CreatedAt, UpdateAt プロパティはデフォルトの 1/1/0001 12:00:00 AM となり、int 型の TestData プロパティはデフォルトの 0 になる。

一方 SQLite のフィールド created_at と updated_at は TEXT 型で NULL 可、フィールド testdata は INTEGER 型で NULL 可。

普通は .NET の DateTime 型から SQLite の TEXT 型への変換は Linq To Enities が良しなにやってくれるが、上記のケースでは小さな親切大きなお世話的に 1/1/0001 12:00:00 AM を NULL に変換する。

ClassDbTFix オブジェクトの int 型の TestData プロパティから SQLite の testdata フィールドへの Lint to Entities による INSERT の場合はそのようなお世話はせず、TestData プロパティのデフォルト値 0 がそのまま INSERT された。

・・・ということではないでしょうか?

SQLite の testdata フィールドの結果が 0 になるのは上記の理由に間違いないと思います。

SQLite のフィールド created_at と updated_at の結果が NULL になるのは上に書いたことは想像の域を出ませんが、それ以外に思いつく理由はありません。

SQLite 側に期待しないで、ClassDbTFix クラスのプロパティにデフォルト値を設定することをお勧めします。

投稿2022/02/22 06:37

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sokafuji

2022/02/22 08:38 編集

頂いた回答をヒントにして、再度検索してみました。 海外のフォーラムがいくつかヒットしたのですが、どうも「Entity Frameworkにおいてデフォルト値の生成を無効にすることは出来ない」というのが本当に正解のようでした。 例えば "INSERT INTO t_fix(testdata) VALUES (77)" のように値を省略したSQLを発行できると、省略したcreated_atやupdated_atにテーブルで設定したDEFAULT値として日時が入るのですが、それはできないようです。 そして、そのフォーラムでも、解決策として「エンティティのコンストラクタで明示的に初期値を入れなさい」と、ご回答頂いたとおりの解決策が提示されていました。 また、値のセットを省略してAdd()した場合に質問のような結果になるのも、ご回答頂いたとおりの挙動のようです。 結果として「テーブルのDEFAULTを有効にすることはできない」ということでしたが、別のアプローチで解決策を教えて頂けました。 これで解決とし、ベストアンサーとさせていただきます。 ありがとうございました。
退会済みユーザー

退会済みユーザー

2022/02/22 09:17

> 結果として「テーブルのDEFAULTを有効にすることはできない」ということでしたが、 それは SQLite 側だけ考えた時は可能ですけど、今回のケースのように Entity Framework でエンティティクラスを使った場合はデフォルト値が INSERT されることになるので、その場合は SQLite で設定したデフォルト値は使われることがないという話でしょう。
退会済みユーザー

退会済みユーザー

2022/02/23 04:03

思い出したことがあるのでご参考までに書いておきます。DateTime プロパティに該当する SQLite のフィールドが NULL 不可の場合は DateTime のデフォルト値はそのまま SQLite に INSERT されます(NULL になることはない)。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問