54

我试图首先将实体框架代码用于一个简单的数据库项目,但遇到了一个我根本无法弄清楚的问题。

我注意到 EF 为我的表设置的 ID 每次自动增加 1,完全忽略了我为该字段手动输入的值。经过一番搜索,我的理解是禁用此行为的正确方法是:

modelBuilder.Entity<Event>().Property(e => e.EventID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);

但是现在我只是收到这个错误,我不知道为什么:

未处理的异常:System.Data.Entity.Infrastructure.DbUpdateException:更新条目时出错。有关详细信息,请参阅内部异常。---

System.Data.UpdateException:更新条目时出错。有关详细信息,请参阅内部异常。---> System.Data.SqlClient.SqlException:当 IDENTITY_INSERT 设置为 OFF 时,无法在表“事件”中插入标识列的显式值。

如果它有帮助,这里是有问题的 POCO 类:

public class Event
{
    [Key, Required]
    public int EventID { get; set; }

    public string EventType { get; set; } //TODO: Event Type Table later on
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }

    public virtual ICollection<Match> Matches { get; set; }
    public virtual ICollection<EventParticipation> EventParticipation { get; set; }
}

提前致谢。

4

2 回答 2

91

由于我更喜欢​​属性,为了完整起见,这里是替代方案:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }

注意:这也适用于 EF Core。

于 2016-05-02T14:02:48.187 回答
41

默认情况下,Entity Framework 假定整数主键是数据库生成的(相当于添加属性HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)Property(e => e.EventID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);在 Fluent API 中调用。

如果您查看创建表的迁移,您应该会看到:

   CreateTable(
                "dbo.Events",
                c => new
                    {
                        EventID = c.Int(nullable: false, identity: true),
                        //etc
                    })
                .PrimaryKey(t => t.EventID );

然后,您使用 Fluent API 将模型更改为DatabaseGenerated.None. EF 将其放入迁移中:

AlterColumn("dbo.Events", "EventID", c => c.Int(nullable: false, identity: false))

生成的sql是这样的:

ALTER TABLE [dbo].[Events] ALTER COLUMN [EventID] [int] NOT NULL

这实际上确实是蹲着。从列中删除 IDENTITY并非易事。您需要删除并重新创建表或创建一个新列,然后您必须复制数据并修复外键。因此,EF 不为您这样做也就不足为奇了。

你需要弄清楚如何最好地为自己做这件事。您可以将迁移回滚到 0 并在指定后从头开始重新构建脚手架DatabaseGeneratedOption.None,或者您可以手动更改迁移以删除并重新创建表。

或者您可以删除并重新创建该列:

DropColumn("Customer", "CustomerId"); 
AddColumn("Customer", "CustomerId", c => c.Long(nullable: false, identity: false));

编辑 或者您可以使用自定义迁移操作打开/关闭身份

于 2013-09-20T12:55:03.300 回答