0

EF5 を使用して新しいエンティティを DB に保存すると、ID 0 のレコードが保存されます。データベースには、1 から始まり 1 をカウントする ID 列があります。

特定のテーブルを再作成すると、すべての問題がなくなりました。しかし、本番環境でずっとテーブルを再作成したくありません。

私はSQLの専門家ではありません。この問題を解決する方法はありますか?MSSQL2005 を使用しています (SQL2012 は注文済みですが、ここに来るまでは使用できず、古いデータベースを新しいデータベースに移行する時間がかかります)。

//Database creation script
    /* [Queue].[DirectDebitOrder] */
CREATE TABLE [Queue].[BookingExportTask](
    [ID] [bigint] IDENTITY(1,1) NOT NULL,
    [DirectDebitRequestID] [bigint] NOT NULL,
    [Type] [nvarchar](50) NOT NULL,
    [Step] [nvarchar](50) NOT NULL,
 CONSTRAINT [PK_Queue_BookingExportTask] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 80) ON [PRIMARY]
) ON [PRIMARY];


/* Foreign Keys */
ALTER TABLE [Queue].[BookingExportTask]  WITH CHECK ADD CONSTRAINT [FK_Queue_BookingExportTask_Queue_BookingExportTaskStepEnum] FOREIGN KEY([Step]) REFERENCES [Queue].[BookingExportTaskStepEnum] ([Name]);
ALTER TABLE [Queue].[BookingExportTask] CHECK CONSTRAINT [FK_Queue_BookingExportTask_Queue_BookingExportTaskStepEnum];

ALTER TABLE [Queue].[BookingExportTask]  WITH CHECK ADD CONSTRAINT [FK_Queue_BookingExportTask_Queue_BookingExportTaskTypeEnum] FOREIGN KEY([Type]) REFERENCES [Queue].[BookingExportTaskTypeEnum] ([Name]);
ALTER TABLE [Queue].[BookingExportTask] CHECK CONSTRAINT [FK_Queue_BookingExportTask_Queue_BookingExportTaskTypeEnum];

ALTER TABLE [Queue].[BookingExportTask]  WITH CHECK ADD CONSTRAINT [FK_Queue_BookingExportTask_Finance_DirectDebitRequest] FOREIGN KEY([DirectDebitRequestID]) REFERENCES [Finance].[DirectDebitRequest] ([ID])
ALTER TABLE [Queue].[BookingExportTask] CHECK CONSTRAINT [FK_Queue_BookingExportTask_Finance_DirectDebitRequest];



//C# Code for saving Entities
    /// <summary>
    /// Saves the data in the <see cref="ILoadableBookingExportTask"/> to the <paramref name="entityContext"/>
    /// </summary>
    /// <param name="entityContext">The <see cref="DBContext"/> context to save the <see cref="ILoadableBookingExportTask"/> to.</param>
    /// <param name="source">The <see cref="ILoadableBookingExportTask"/> to save.</param>
    /// <returns>The <see cref="BookingExportTask"/> that holds the actually stored values.</returns>
    public static BookingExportTask Save(this DBContext entityContext, ILoadableBookingExportTask source)
    {
        if (source == null) { return null; }
        return source.SaveTo(entityContext.BookingExportTask.EnsureExists(source), entityContext);
    }

    /// <summary>
    /// Helper. Finds existing instance or creates a new instance of <typeparamref name="TEntityType"/> which is immediately added to the <see cref="dbSet{TEntityType}"/> as well. 
    /// </summary>
    /// <typeparam name="TEntityType">The type of the entity to check.</typeparam>
    /// <param name="dbSet">The database collection for the entity.</param>
    /// <param name="entity">The <see cref="IEntity"/> to find.</param>
    /// <returns>The existing or newly created <typeparamref name="TEntityType"/>.</returns>
    public static TEntityType EnsureExists<TEntityType>(this DbSet<TEntityType> dbSet, IEntity entity)
        where TEntityType : class, IEntity, new()
    {
        if (entity == null) { return default(TEntityType); }
        return dbSet.EnsureExists(entity.ID);

    }

    /// <summary>
    /// Helper. Finds existing instance or creates a new instance of <typeparamref name="TEntityType"/> which is immediately added to the <see cref="dbSet{TEntityType}"/> as well. 
    /// </summary>
    /// <typeparam name="TEntityType">The type of the entity to check.</typeparam>
    /// <param name="dbSet">The collection to check for existance of the entity.</param>
    /// <param name="id">The ID of the entity to find.</param>
    /// <returns>The existing or newly created <typeparamref name="TEntityType"/>.</returns>
    public static TEntityType EnsureExists<TEntityType>(this DbSet<TEntityType> dbSet, long id)
        where TEntityType : class, IEntity, new()
    {
        return dbSet.GetByID(id) ?? dbSet.New();
    }


    /// <summary>
    /// Saves the data in the <see cref="ILoadableBookingExportTask"/> to the <paramref name="entityContext"/>
    /// </summary>
    /// <param name="source">The <see cref="ILoadableBookingExportTask"/> to save.</param>
    /// <param name="target">The <see cref="BookingExportTask"/> to save the data to.</param>
    /// <param name="entityContext">The <see cref="DBContext"/> context to save the <see cref="ILoadableBookingExportTask"/> to.</param>
    /// <returns>The <see cref="BookingExportTask"/> that holds the actually stored values.</returns>
    private static BookingExportTask SaveTo(this ILoadableBookingExportTask source, BookingExportTask target, DBContext entityContext)
    {
        if (source == null) { return target; }
        Debug.WriteLine(string.Format("Saving ILoadableBookingExportTask {0} to DBContext.", target.ID));

        /* copy all fields from source to target. Use SyncLinkedObject for all linked entities to ensure the saving of possible changes to the foreign entities.
         * target.Field = target.Field;
         * target.RelatedEntity = entityContext.SyncLinkedObject(source.RelatedEntity, source.RelatedEntity_ForeignKey);
         * 
         * Note: It's useless to overwrite the Identity property - like target.ID. Just skip it.
         */

        return target;
    }

要するにC#コード:

  1. エンティティが既に存在するかどうかを確認します (新しいエンティティなのでいいえ)
  2. コンテキスト内の特定の DBSet に新しいエンティティを作成する
  3. ビジネスエンティティの値を dbset-entity に渡します (ID なし)
  4. コンテキストを保存する

これまでは正常に動作しています。DBが変更または復元されます。その後、Identity 列を含むテーブルを再作成する必要があります。テーブルを再作成しない場合、最初の新しいエンティティは ID 0 に保存されます。その瞬間からの ensureExists メソッドにより、新しいエンティティはすべて既存のエンティティを上書きします。これは、ID 0 のために論理的です。

問題は、ID 列が EF から認識されないことです。

この問題が発生した場合は、SQL プロファイラーで DB を監視しました。ID を取得する SQL 管理スタジオでプロファイラーが見つけた受信クエリを貼り付けました。したがって、DBは問題ないようです。コードは変更されておらず、以前 (DB の復元前) に機能していました。これまでに見つけた唯一の解決策は、ID 列を含むテーブルを再作成することです。その後、C# コードは適応なしで再び機能します。

4

1 に答える 1

0

テーブルに列があることを絶対に確信していIDENTITYますか? 私が尋ねる理由は、IDが なしで作成された場合IDENTITY、データ注釈またはFluentAPI. IDENTITYとして開始し(整数 ID フィールドのデフォルト)、オフにしたい場合も同じ問題です。

テーブルを削除して再作成すると修正されます。

まだ開発中で、テーブルが空の場合は、データベースで変更できます。

それはあなたのシナリオに依存します。本番環境になった後に列を変更することはほとんどないと思いますが、必要な場合は、カスタム移行操作で ID のオン/オフを切り替えることで実行できます。

参照:

Entity Framework の ID 問題

于 2013-11-15T09:53:26.713 に答える