无法在表实体框架中插入标识列的显式值

Posted

技术标签:

【中文标题】无法在表实体框架中插入标识列的显式值【英文标题】:Cannot insert explicit value for identity column in table Entity Framework 【发布时间】:2020-11-22 16:31:18 【问题描述】:

我有一个在我的数据库中存储股票的表单,当我输入一个股票时,它会保留信息,当我尝试添加另一只股票时,我得到一个异常“无法为表中的标识列插入显式值”

在我的模型中,我声明了 STOCKID 属性,在我的 T-SQL 中,它设置为 IDENTITY(1,1)

在我的模型中,我添加了[DatabaseGenerated(DatabaseGeneratedOption.Identity)],但这并没有帮助

有什么建议吗?

型号

public class Stock

    #region Day 1's

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]       
    public int Id  get; set; 

T-SQL

CREATE TABLE [dbo].[LowFloatStocks] 
(
    [Id]                   INT             IDENTITY (1, 1) NOT NULL,
    [Date]                 DATE            NOT NULL,
    [Ticker]               NVARCHAR (4)    NOT NULL,
    [PreviousClose]        DECIMAL (4, 2)  DEFAULT ((4.00)) NOT NULL,
    [PM_OpeningPrice]      DECIMAL (18, 2) DEFAULT ((3)) NOT NULL,
    [OpeningPrice]         DECIMAL (18, 2) NOT NULL,
    [PMFadePercent]        AS (ROUND(([OpeningPrice] - [PM_OpeningPrice]) / [PM_OpeningPrice], (4)) * (100.0)) PERSISTED NOT NULL,
    [GainPercent]          AS (ROUND(([High] - [OpeningPrice]) / [OpeningPrice], (4)) * (100.0)) PERSISTED NOT NULL,
    [GapPercent]           AS (ROUND(([OpeningPrice] - [PreviousClose]) / [PreviousClose], (4)) * (100.0)) PERSISTED NOT NULL,
    [Spike]                DECIMAL (18, 2) NOT NULL,
    [1stSpike%]            AS (ROUND(([Spike] - [OpeningPrice]) / [OpeningPrice], (4)) * (100.0)) PERSISTED NOT NULL,
    [High]                 DECIMAL (18, 2) NOT NULL,
    [HighPercent]          AS (ROUND(([High] - [PreviousClose]) / [PreviousClose], (4)) * (100.0)) PERSISTED NOT NULL,
    [Low]                  DECIMAL (18, 2) NOT NULL,
    [LowPercent]           AS (ROUND(([Low] - [PreviousClose]) / [PreviousClose], (4)) * (100.0)) PERSISTED NOT NULL,
    [Close]                DECIMAL (18, 2) DEFAULT ((4)) NOT NULL,
    [ClosePercent]         AS              (round(([Close]-[PreviousClose])/[PreviousClose],(4))*(100.0)) PERSISTED NOT NULL,
    [ClosevHigh]           AS              (round(([High]-[Close])/[Close], (4))*(100)) PERSISTED NOT NULL,
    [ClosevOpen]           AS              (round(([OpeningPrice]-[Close])/[OpeningPrice],(4))*(100.0)) PERSISTED NOT NULL,
    [CloseLessEqualToOpen] AS              (CONVERT([nchar](3),case when [Close]<=[OpeningPrice] then 'Yes' else 'No' end)) PERSISTED NOT NULL,
    [CloseRed]             AS              (CONVERT([nchar](3),case when [Close]<[OpeningPrice] then 'Yes' else 'No' end)) PERSISTED NOT NULL,
    [Catalyst]             NVARCHAR (50)   NOT NULL,
    [Float]                DECIMAL (18, 3) NOT NULL,
    [Dilution]             NCHAR (3)       NOT NULL,

    PRIMARY KEY CLUSTERED ([Id] ASC)
);

添加库存方法

public ICommand AddCommand => _addCommand ?? (_addCommand = new RelayCommand(param => this.AddStock()));


    #endregion 

    #region Actions

    private void AddStock()
    
        using (var stocks = new AppDbContext())
        
            stocks.LowFloatStocks.Add(stock);
            stocks.SaveChanges();
            Stocks = stocks.LowFloatStocks.ToList();
            Clear();


        
    

【问题讨论】:

您是否添加了迁移并更新了数据库? 先是数据库?我必须使用迁移吗 您是否也在使用 fluent API 进行配置?你能显示插入数据库的代码吗 stock.Id的值是多少 是的,所以在保存之前尝试将其显式设置为 0。试一试 【参考方案1】:

如果您想自己创建密钥,您应该使用[DatabaseGenerated(DatabaseGeneratedOption.None)][DatabaseGenerated(DatabaseGeneratedOption.Identity)] 表示您让数据库处理主键的创建。这通常是最佳选项,因为您的软件的两个实例尝试创建相同的主键将导致错误。这是一个不太可能的场景,但仍然:让数据库创建主键。当您使用 Database First 时,您没有在不更新数据库的情况下更改 DatabaseGeneratedOption 的选项。如果您从数据库创建了 Code First 模型,则可以选择更改 DatabaseGeneratedOption、创建新的迁移和更新数据库。但这可能是不可取的,因为实体框架可能会删除整个表并重新创建它。

请显示创建在stocks.LowFloatStocks.Add(stock); 中添加的实体的代码。你给Id赋值了吗?如果是这样,请尽量不要这样做。

否则,请尝试@viveknuna 在评论中建议的解决方案:

stock.Id = 0; 
stocks.LowFloatStocks.Add(stock); 
stocks.SaveChanges();

【讨论】:

我确实希望数据库自己创建密钥,但我不明白为什么它在第一个条目而不是第二个条目上创建? @罗伯特·班特勒 低流通股只是一个`public DbSet LowFloatStocks get;放; ` 是的,但我感兴趣的是创建“股票”的代码如果您列表中的第一个条目的 ID 值为 0(这是“int”的默认值),那么它将工作。但是如果下一个条目由于某种原因获得值 1,则插入将失败,因为您手动为 DatabaseGenerated 属性分配了一个值 我的文本框绑定到我的股票属性 '`public string Ticker get return stock.Ticker; 设置 股票.Ticker = 价值; OnPropertyChanged("Ticker"); public DateTime Date get return Date = stock.Date; 设置 股票。日期 = 价值;

以上是关于无法在表实体框架中插入标识列的显式值的主要内容,如果未能解决你的问题,请参考以下文章

无法首先在表 ef6 db 中插入标识列的显式值

使用 C# 出现错误“无法在表中插入标识列的显式值”

当 IDENTITY_INSERT 设置为 OFF 时,无法在表“企业”中插入标识列的显式值

当 IDENTITY_INSERT 设置为 OFF 时,无法在表中插入标识列的显式值

当 IDENTITY_INSERT 设置为 OFF 时,SQL 无法在表“表”中插入标识列的显式值 [重复]

SqlException:当 IDENTITY_INSERT 设置为 OFF 时,无法在表“任务”中插入标识列的显式值