web-dev-qa-db-ja.com

サーバーで生成されたキーとサーバーで生成された値は、SQL ServerCompactではサポートされていません

エンティティフレームワークを使い始めたばかりなので、既存のSQL ServerCEデータベースに接続することにしました。 IDENTITY(1、1)主キーを持つテーブルがありますが、エンティティを追加しようとすると、上記のエラーが発生します。

から MS Technet artice 私はそれを学びました

SQL Server Compactは、Entity Frameworkで使用される場合、サーバーで生成されたキーまたは値を持つエンティティをサポートしません。 Entity Frameworkを使用する場合、エンティティのキ​​ーはサーバー生成としてマークされる場合があります。これにより、データベースは挿入時またはエンティティ作成時にキーの値を生成できます。さらに、エンティティの0個以上のプロパティが、サーバーで生成された値としてマークされる場合があります。詳細については、EntityFrameworkドキュメントの「StoreGeneratedPattern」トピックを参照してください。 SQL Server Compactは、Entity Frameworkで使用する場合、サーバーで生成されたキーまたは値を持つエンティティをサポートしませんが、Entity Frameworkでは、サーバーで生成されたキーまたは値を使用してエンティティタイプを定義できます。サーバーで生成された値を持つエンティティに対するデータ操作操作は、「サポートされていません」例外をスローします。

だから今私はいくつかの質問があります:

  • キーがサポートされておらず、例外がスローされる場合、なぜキーをサーバー生成としてマークするのですか?引用された段落から意味をなすのは難しいです。
  • StoreGeneratedPattern = "Identity"をエンティティのプロパティに追加しようとすると、Studioは許可されていないと文句を言いました。私が間違っているのは何ですか?
  • この制限(別のDBへの切り替えを含む)の最善の回避策は何ですか?私の制限は、ゼロインストールとエンティティフレームワークの使用です。
35

この制限に達したとき、タイプをuniqueidentifierに変更しました

24
mostlytech

Uniqueidentifierを使用するか、bigint/intキー値を手動で生成するのが最善のオプションです。

おそらくこのようなもの...

    private static object lockObject = new object();

    private static long nextID = -1;

    public static long GetNextID()
    {
        lock (lockObject)
        {
            if (nextID == -1) nextID = DateTime.UtcNow.Ticks; else nextID++;
            return nextID;
        }
    }

これは、アプリケーションの実行中にティックごとに複数のレコードを生成しないことを前提としています(さらに停止して再起動する時間)。これは私が信じる合理的な仮定ですが、完全に防弾の(しかしより複雑な)ソリューションが必要な場合は、データベースから最大のIDを読み取り、そこからインクリメントしてください。

17
Hightechrider

SQL CEバージョン4.0は、EntityFrameworkプロバイダーでこの問題を修正しました。

6
Pablonete

私もこの問題にぶつかりました...ほとんどの場合、techの答えがおそらく最良の選択肢であり、GUIDは非常に使いやすく、キーの衝突のリスクは非常に低いです(存在しないわけではありませんが)。

  • キーがサポートされておらず、例外がスローされる場合、なぜキーをサーバー生成としてマークするのですか?引用された段落から意味をなすのは難しいです。

SQL Server(Compactではない)がサポートしているため、他のサードパーティもサポートしている可能性があります... EntityFrameworkはSQLServer Compact専用ではありません;)

4
Thomas Levesque

私の場合、すべてのクラスに「ID」という名前の主キーがあります

インターフェースを作成しました

public class IID
{
    public Int32 ID { get; set; }
}

次に、拡張メソッドを作成します

public static Int32 GetNextID<T>(this ObjectSet<T> objects)
    where T : class, IID
    {
        T entry = objects.OrderByDescending(u => u.ID).FirstOrDefault();
        if (entry == default(T))
            return 1;
        return entry.ID + 1;
    }

次に、新しいIDが必要な場合は、次のようにします。

MyObject myobj = new MyObject();
myobj.ID = entities.MyTable.GetNextID();
4

もう1つのオプションは、ID列を持つテーブルでSqlCeResultSetを使用することです。

1
user544111

データ型がINT32のIDという名前の主キーがあり、ID列があります

これを行うだけです

MyEntity Entity = new MyEntity();

文字列コマンド;

command = "Insert into Message(Created、Message、MsgType)values('12/1/2014 '、' Hello World '、5); Entity.ExecuteStoreCommand(command);

--insertステートメントで主キーを除外します

--SQLCEはシステムで生成されたキーをサポートしていないため

--LINQは、データ型がINTの主キーにデフォルト値の0を提供するため、使用しないでください。

0
Ian