簡體   English   中英

ASP.NET MVC OptimisticConcurrencyException

[英]ASP.NET MVC OptimisticConcurrencyException

我正在嘗試使用將列表作為上一頁中的參數的函數寫入數據庫中的兩個表。 我調用數據庫以檢索purchase_order_no,因為該列是在輸入時生成的IDENTITY主鍵。

楷模:

采購訂單

    [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; }

訂單詳情

    [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; }

嘗試將新的“ purchase_order”模型插入數據庫時​​收到此錯誤:

存儲更新,插入或刪除語句影響了意外的行數(0)。 自加載實體以來,實體可能已被修改或刪除。 有關了解和處理樂觀並發異常的信息,請參見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);

        }
    }

我認為問題出在您的模型課上。 purchase_order ,為什么有這么多列標記為[Key] 由於purchase_order_no被聲明為標識列,因此它本身應該是主鍵。 我什至不知道為什么EF在啟動時不會抱怨,因為您的配置沒有意義。

刪除所有其他列上的[Key]屬性,它應該可以工作。 如果需要確保唯一性,則可以在其他列上創建唯一索引。

我不會對您的模型提出疑問,因為您為什么首先會有如此多的列標記為[Key]。 那無助於您解決問題。 此外,出於性能方面的考慮,您可能希望主鍵中包含所有這些列:當首先將代碼與EF一起使用時,默認情況下,主鍵創建為集群

問題可能不是屬性[Key]的列 在主鍵中僅合並了一個DateTime類型的額外列之后,我遇到了同樣的問題,並且您在實體Purchase_order的主鍵組合中也有一個DateTime列。

當標記為主鍵的一部分時,EF似乎不能很好地處理DateTime列。 我找到了一個有趣的網頁來確認這一點: https : //social.msdn.microsoft.com/Forums/en-US/6f545446-aa26-4a21-83e9-60f7fa5ed3b0/optimisticconcurrencyexception-when-trying-to-insert-a-new在表中使用實體框架記錄?論壇= adodotnetentityframework

我可以為您的問題想到兩種解決方案:

  1. 如果要堅持使用主鍵定義:將[order_timestamp]截斷為數據庫可以接受的值。 如果使用SQL Server,則在將C#截斷為10毫秒時會做的很好:

     order_timestamp = DateTime.Now.Truncate(TimeSpan.FromMilliseconds(10)); 
  2. 如果您不想截斷時間戳,但希望將PK組合更改為索引,請考慮為主鍵添加一個自動編號列:

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

    並將其他關鍵屬性更改為:

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

    為了提高性能,您可能希望將索引創建為集群:

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

    但是,當使用Migrations時 ,請記住,不幸的是EF仍然會嘗試將您的PK也創建為集群的。 這將在發出命令update-database時產生錯誤,您首先必須稍稍更改遷移代碼。 盡管在代碼中您會發現類似以下內容:

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

    您必須通過將PK部分的遷移代碼更改為以下內容來明確聲明主鍵為非集群鍵:

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

我希望這有幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM