简体   繁体   English

SqlException:当 IDENTITY_INSERT 设置为 OFF 时,无法为表 [表名] 中的标识列插入显式值

[英]SqlException: Cannot insert explicit value for identity column in table [Table name] when IDENTITY_INSERT is set to OFF

I am creating a website for expense tracking and when I send a new POST request calling AddNew method to add a new Entry I get this error:我正在创建一个用于费用跟踪的网站,当我发送一个新的 POST 请求调用AddNew方法来添加一个新条目时,我收到此错误:

SqlException: Cannot insert explicit value for identity column in table 'Accounts' when IDENTITY_INSERT is set to OFF. SqlException:当 IDENTITY_INSERT 设置为 OFF 时,无法为表“Accounts”中的标识列插入显式值。 Cannot insert explicit value for identity column in table 'Categories' when IDENTITY_INSERT is set to OFF.当 IDENTITY_INSERT 设置为 OFF 时,无法为表 'Categories' 中的标识列插入显式值。

public class Entry
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    public string Description { get; set; }
    public decimal MoneyAmount { get; set; }
    public virtual Account Account { get; set; }
    public virtual Category Category { get; set; }
    public string CreatedTimestamp { get; set; }
}

public class Account
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual User User { get; set; }
    //public byte[] BankApi { get; set; }
    public decimal MoneyAmount { get; set; }
    public string CreatedTimestamp { get; set; }
    public virtual ICollection<Entry> Entries { get; set; }
}

public class Category
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual EntryType EntryType { get; set; }
    public virtual ICollection<Entry> Entries { get; set; }
}

public interface IEntryService
{
    void AddNew(Entry entry);
}

public class EntryService : IEntryService
{
    private DataContext _context;

    public EntryService(DataContext context)
    {
        _context = context;
    }

    public void AddNew(Entry entry)
    {
        entry.CreatedTimestamp = DateTime.Now.ToString();

        _context.Entries.Add(entry);
        _context.SaveChanges();
    }
}

Here is my postman request:这是我的邮递员请求:

邮递员请求

Account with ID == 1, and Category with ID == 1 both exist already in the respective databases. ID == 1 的帐户和 ID == 1 的类别都已存在于各自的数据库中。

Also, when I am inserting values to Account database, whose method looks exactly the same as AddNew for entries, it works without a problem.此外,当我向 Account 数据库插入值时,其方法与条目的AddNew完全相同,它可以正常工作。

Does anyone know what is this about?有谁知道这是关于什么的?

The issue is that you are passing entities with relations back to the server.问题是您将具有关系的实体传递回服务器。 Each request is served by a different DB Context so while your Entry with it's associated Account and Category look like entities, they are not.每个请求都由不同的数据库上下文提供服务,因此虽然您的条目及其关联的帐户和类别看起来像实体,但它们不是。 They are deserialized POCO objects that the DbContext knows nothing about.它们是 DbContext 一无所知的反序列化 POCO 对象。 When you pass an entity referencing other entities that already exist in the database, the receiving context does not know about these entities, so it interprets them as new records and tries to insert them.当您传递引用数据库中已存在的其他实体的实体时,接收上下文不知道这些实体,因此它将它们解释为新记录并尝试插入它们。

My default recommendation is to never pass entities between client and server.我的默认建议是永远不要在客户端和服务器之间传递实体。 This leads to serialization errors & performance issues from server to client, and exposes your system to tampering, plus issues like this with insert errors or duplication when used from client to server.这会导致从服务器到客户端的序列化错误和性能问题,并使您的系统暴露于篡改,以及在从客户端到服务器使用时插入错误或重复等问题。

To solve your issue without too much of a change:要在没有太多更改的情况下解决您的问题:

public void AddNew(Entry entry)
{
    entry.CreatedTimestamp = DateTime.Now.ToString();
    var account = _context.Accounts.Single(x => x.Id = entry.Account.Id);
    var category = _context.Categories.Single(x => x.Id = entry.Category.Id);
    entry.Account = account; 
    entry.Category = category;
    _context.Entries.Add(entry);
    _context.SaveChanges();
}

This associates the entry account and category with instances known by the context.这将条目帐户和类别与上下文已知的实例相关联。

An alternative would be to attach the account and category passed back to the DbContext.另一种方法是将传递回 DbContext 的帐户和类别附加到。 This would also work, however it can make your system vulnerable to tampering.这也可以,但它会使您的系统容易受到篡改。 The data passed back to the controller can be intercepted by debugging tools or sniffers on a client machine where the data in the message can be altered to change details in records and their related records in ways you don't intend.传回控制器的数据可以被客户端机器上的调试工具或嗅探器截获,其中可以更改消息中的数据,以您不希望的方式更改记录及其相关记录中的详细信息。 If for any reason any code ends up setting those re-attached entities to a Modified state, those alterations would be persisted to the database on SaveChanges.如果出于任何原因,任何代码最终将这些重新附加的实体设置为修改状态,则这些更改将在 SaveChanges 上持久保存到数据库中。 Attaching entities can also be a nuisance when dealing with multiple detached references.在处理多个分离的引用时,附加实体也很麻烦。 For instance if you are saving multiple records at a time with relatives.例如,如果您一次与亲戚保存多条记录。 Attaching each will work fine when all relatives are unique, but without the extra logic to check each one to see if there is already an attached reference, you can get errors when a second reference to an already attached (or loaded) entity attach is attempted.当所有亲戚都是唯一的时,附加每个都可以正常工作,但是如果没有额外的逻辑来检查每个人以查看是否已经附加了引用,则在尝试对已附加(或加载)实体附加的第二个引用时,您可能会收到错误. This means more code to check the local association and replace it if found.这意味着更多的代码来检查本地关联并在找到时替换它。

I just changed Entry model from我刚刚改变了条目模型

public class Entry
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    public string Description { get; set; }
    public decimal MoneyAmount { get; set; }
    public virtual Account Account { get; set; }
    public virtual Category Category { get; set; }
    public string CreatedTimestamp { get; set; }
}

To this:对此:

 public class Entry
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }
        public string Description { get; set; }
        public decimal MoneyAmount { get; set; }
        public int AccountId { get; set; }
        public int CategoryId { get; set; }
        public string CreatedTimestamp { get; set; }
    }

And everything seems to work fine now.现在似乎一切正常。 C# does its magic and picks AccountId and CategoryId as foreign keys. C# 发挥了它的魔力,并选择 AccountId 和 CategoryId 作为外键。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 SqlException:当 IDENTITY_INSERT 设置为 OFF 时,无法在表 'Ogretmenler' 中为标识列插入显式值 - SqlException: Cannot insert explicit value for identity column in table 'Ogretmenler' when IDENTITY_INSERT is set to OFF SqlException:当IDENTITY_INSERT设置为OFF时,无法为表&#39;Recipe&#39;中的Identity列插入显式值 - SqlException: Cannot insert explicit value for identity column in table 'Recipe' when IDENTITY_INSERT is set to OFF SqlException:当IDENTITY_INSERT设置为OFF时,无法为表&#39;AspNetUsers&#39;中的Identity列插入显式值 - SqlException: Cannot insert explicit value for identity column in table 'AspNetUsers' when IDENTITY_INSERT is set to OFF SqlException:当IDENTITY_INSERT设置为OFF时,无法为表&#39;&#39;中的标识列插入显式值 - SqlException: Cannot insert explicit value for identity column in table '' when IDENTITY_INSERT is set to OFF SqlException:当 IDENTITY_INSERT 设置为 OFF 时,无法在表“任务”中插入标识列的显式值 - SqlException: Cannot insert explicit value for identity column in table 'Tasks' when IDENTITY_INSERT is set to OFF ASP.NET MVC 错误 SqlException:当 IDENTITY_INSERT 设置为 OFF 时,无法在表“用户”中插入标识列的显式值 - ASP.NET MVC error SqlException: Cannot insert explicit value for identity column in table 'Users' when IDENTITY_INSERT is set to OFF EF Core SqlException:当 IDENTITY_INSERT 设置为 OFF 时,无法在表“MenuCategories”中插入标识列的显式值 - EF Core SqlException: Cannot insert explicit value for identity column in table 'MenuCategories' when IDENTITY_INSERT is set to OFF SqlException:当 IDENTITY_INSERT 设置为 OFF ASP.NET Core 2.1 时,无法在表“类别”中插入标识列的显式值 - SqlException: Cannot insert explicit value for identity column in table 'Categories' when IDENTITY_INSERT is set to OFF ASP.NET Core 2.1 实体框架:当IDENTITY_INSERT设置为OFF时,无法为表&#39;[table]&#39;中的标识列插入显式值 - Entity Framework: Cannot insert explicit value for identity column in table '[table]' when IDENTITY_INSERT is set to OFF 出现错误:当IDENTITY_INSERT设置为OFF时,无法在表&#39;Table&#39;中为标识列插入显式值 - Getting Error: Cannot insert explicit value for identity column in table 'Table' when IDENTITY_INSERT is set to OFF
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM