使用EF向数据库添加记录不会使用正确的ID保存记录,而是保存到ID 0

时间:2013-11-15 09:20:13

标签: sql entity-framework sql-server-2005 entity-framework-5

使用EF5将新实体保存到数据库时会保存ID为0的记录。数据库的标识列以1开头并计数为1.

当我重新创建特定的表时,所有问题都消失了。但我不想一直在我的生产环境中重新创建表格。

我不是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. 保存上下文
  5. 这是好的工作,直到。数据库已更改或恢复。之后,必须重新创建具有Identity列的表。如果我不重新创建表,则第一个NEW实体将保存到ID 0.使用ensureExists方法,从那时起的新实体将覆盖现有实体,这是因为ID为0,这是合乎逻辑的。

    问题是EF无法识别标识列。

    如果出现此问题,我使用SQL事件探查器监视数据库。我在SQL管理工作室中粘贴了探查器发现的崩溃查询,在那里我获取了我的ID。所以看起来DB很好。代码在更改之前(在恢复数据库之前)不会更改和工作。到目前为止,我找到的唯一解决方案是使用标识列重新创建表。之后,C#代码再次正常工作而没有适应。

1 个答案:

答案 0 :(得分:0)

您是否完全确定该表格中有IDENTITY列?我问的原因是如果创建ID而没有IDENTITY,如果您尝试通过数据注释或FluentAPI尝试启用它,则实体框架不会修复它。如果它以IDENTITY(这是整数ID字段的默认值)开始并且您想要将其关闭,则会出现同样的问题。

删除表并重新创建它将解决它。

如果它仍在开发中且表是空的,您可以在数据库中更改它。

这取决于您的情况。我认为在生产后要更改专栏是非常罕见的,但如果必须,可以通过Switching Identity On/Off With A Custom Migration Operation

进行修改。

参考:

Identity problem in Entity Framework