简体   繁体   English

ASP.NET MVC OptimisticConcurrencyException

[英]ASP.NET MVC OptimisticConcurrencyException

I am trying to write to two tables in my database in a function that takes in lists as a parameter from the previous page. 我正在尝试使用将列表作为上一页中的参数的函数写入数据库中的两个表。 I call the db to retrieve the purchase_order_no because the column is an IDENTITY primary key that is generated on entry. 我调用数据库以检索purchase_order_no,因为该列是在输入时生成的IDENTITY主键。

Models: 楷模:

purchase_order 采购订单

    [Key]
    [Column(Order = 0)]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int client_no { get; set; }

    [Key]
    [Column(Order = 1)]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int purchase_order_no { get; set; }

    [StringLength(60)]
    public string name { get; set; }

    [Key]
    [Column(Order = 2)]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int order_group_no { get; set; }

    [StringLength(24)]
    public string purchase_order_reference { get; set; }

    [Key]
    [Column(Order = 3)]
    public DateTime order_timestamp { get; set; }

order_detail 订单详情

    [Key]
    [Column(Order = 0)]
    public long order_detail_no { get; set; }

    [Key]
    [Column(Order = 1)]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int purchase_order_no { get; set; }

    [Key]
    [Column(Order = 2)]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int inventory_no { get; set; }

    [Key]
    [Column(Order = 3)]
    public decimal quantity { get; set; }

    public int? vendor_no { get; set; }

I receive this error when trying to insert my new 'purchase_order' model into the db: 尝试将新的“ purchase_order”模型插入数据库时​​收到此错误:

Store update, insert, or delete statement affected an unexpected number of rows (0). 存储更新,插入或删除语句影响了意外的行数(0)。 Entities may have been modified or deleted since entities were loaded. 自加载实体以来,实体可能已被修改或删除。 See http://go.microsoft.com/fwlink/?LinkId=472540 for information on understanding and handling optimistic concurrency exceptions. 有关了解和处理乐观并发异常的信息,请参见http://go.microsoft.com/fwlink/?LinkId=472540

    [HttpPost]
    public ActionResult orderForm (List<int> quantity, List<string> itemName, List<int> inventory_no, List<int> client_no, List<int> vendorCode, int orderGroupNo)
    {
        using (var db = new db_model())
        {
            var ctx = ((IObjectContextAdapter)db).ObjectContext;
            purchaseOrderVM poVM = new purchaseOrderVM();
            List<order_detail> tempList = new List<order_detail>();
            purchase_order po = new purchase_order();
            po.client_no = client_no[0];
            var purchaseOrder = db.purchase_order.Where(x => x.client_no == po.client_no).Max(x => x.purchase_order_no);
            po.order_group_no = orderGroupNo;
            po.order_timestamp = DateTime.Now;
            db.purchase_order.Add(po);
            try
            {
                db.SaveChanges(); <!-- This is where I get the error -->
            }
            catch (OptimisticConcurrencyException e)
            {
                ctx.Refresh(RefreshMode.ClientWins, db.purchase_order);
                throw e;

            }
            for (int i = 0; i < itemName.Count(); i++)
            {
                order_detail od = new order_detail();
                od.purchase_order_no = db.purchase_order.Where(x => x.client_no == po.client_no).Max(x => x.purchase_order_no);
                od.inventory_no = inventory_no[i];
                od.quantity = quantity[i];
                od.vendor_no = vendorCode[i];
                db.order_detail.Add(od);
                try
                    {
                        db.SaveChanges();
                    }
                catch (OptimisticConcurrencyException e)
                    {
                        ctx.Refresh(RefreshMode.ClientWins, db.order_detail);
                        throw e;
                    }
                tempList.Add(od);
            }
            poVM.purchase_order = po;
            poVM.orderList = tempList;
            return View(poVM);

        }
    }

I think the problem is in your model class. 我认为问题出在您的模型课上。 In purchase_order , why do you have so many columns flagged as [Key] ? purchase_order ,为什么有这么多列标记为[Key] As purchase_order_no is declared as an identity column, it should be the primary key by itself. 由于purchase_order_no被声明为标识列,因此它本身应该是主键。 I don't even know why EF doesn't complain at startup, because your configuration makes no sense. 我什至不知道为什么EF在启动时不会抱怨,因为您的配置没有意义。

Remove the [Key] attribute on all other columns, and it should work. 删除所有其他列上的[Key]属性,它应该可以工作。 If you need to ensure uniqueness, you can create a unique index on the other columns. 如果需要确保唯一性,则可以在其他列上创建唯一索引。

I will not question your model as to why you have so many columns flagged as [Key] in the first place. 我不会对您的模型提出疑问,因为您为什么首先会有如此多的列标记为[Key]。 That's not helping you with your problem. 那无助于您解决问题。 Moreover, you might want all those columns in your primary key for performance reasons: when using code first with EF, the primary key is created as clustered by default. 此外,出于性能方面的考虑,您可能希望主键中包含所有这些列:当首先将代码与EF一起使用时,默认情况下,主键创建为集群

The problem is probably not the number of columns with attribute [Key]. 问题可能不是属性[Key]的列 I had the same problem after incorporating just one extra column of type DateTime in the primary key, and you also have a DateTime column in your primary key combination for entity purchase_order. 在主键中仅合并了一个DateTime类型的额外列之后,我遇到了同样的问题,并且您在实体Purchase_order的主键组合中也有一个DateTime列。

It looks like EF is not handling DateTime columns very well, when marked as part of the primary key. 当标记为主键的一部分时,EF似乎不能很好地处理DateTime列。 I found an interesting webpage that confirms this: https://social.msdn.microsoft.com/Forums/en-US/6f545446-aa26-4a21-83e9-60f7fa5ed3b0/optimisticconcurrencyexception-when-trying-to-insert-a-new-record-in-table-using-entity-framework?forum=adodotnetentityframework 我找到了一个有趣的网页来确认这一点: https : //social.msdn.microsoft.com/Forums/en-US/6f545446-aa26-4a21-83e9-60f7fa5ed3b0/optimisticconcurrencyexception-when-trying-to-insert-a-new在表中使用实体框架记录?论坛= adodotnetentityframework

I can think of two solutions for your problem: 我可以为您的问题想到两种解决方案:

  1. If you want to stick with your primary key definition: truncate your [order_timestamp] to a value your database does accept. 如果要坚持使用主键定义:将[order_timestamp]截断为数据库可以接受的值。 In case of SQL Server you'll be doing fine when truncating to 10 msec, C#: 如果使用SQL Server,则在将C#截断为10毫秒时会做的很好:

     order_timestamp = DateTime.Now.Truncate(TimeSpan.FromMilliseconds(10)); 
  2. If you don't want to truncate your timestamp but accept to change your PK combination to an index: consider adding an autonumber column for the primary key: 如果您不想截断时间戳,但希望将PK组合更改为索引,请考虑为主键添加一个自动编号列:

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

    and changing the other key attributes to: 并将其他关键属性更改为:

     [Index("IX_purchase_order", Order = 1)], [Index("IX_purchase_order", Order = 2)], etc. 

    For performance, you might want the index to be created as clustered: 为了提高性能,您可能希望将索引创建为集群:

     [Index("IX_purchase_order", IsClustered = true, Order = 1)], etc. 

    But when using Migrations , bear in mind that unfortunately EF will still try to create your PK as clustered as well. 但是,当使用Migrations时 ,请记住,不幸的是EF仍然会尝试将您的PK也创建为集群的。 This would give errors when issuing command update-database , you first will have to change your migration code a little. 这将在发出命令update-database时产生错误,您首先必须稍稍更改迁移代码。 Although in the code you will find something like: 尽管在代码中您会发现类似以下内容:

     .Index(t => new{client_no, ..., order_timestamp}, clustered: true, name: "IX_purchase_order") 

    you explicitly must declare the primary key non-clustered , by changing the migration code for the PK part to: 您必须通过将PK部分的迁移代码更改为以下内容来明确声明主键为非集群键:

     .PrimaryKey(t => t.Id, clustered: false) 

I hope this helps. 我希望这有帮助。

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM