ASP.NET MVC OptimisticConcurrencyException
ASP.NET MVC OptimisticConcurrencyException
我正在尝试在一个函数中写入数据库中的两个表,该函数将上一页的列表作为参数。我调用数据库来检索 purchase_order_no,因为该列是在输入时生成的 IDENTITY 主键。
型号:
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; }
我在尝试将我的新 'purchase_order' 模型插入数据库时收到此错误:
Store update, insert, or delete statement affected an unexpected number of rows (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.
[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);
}
}
我认为问题出在您的模型中 class。在 purchase_order
中,为什么有这么多列标记为 [Key]
?由于 purchase_order_no
被声明为标识列,因此它本身应该是主键。我什至不知道为什么 EF 在启动时不抱怨,因为你的配置没有意义。
删除所有其他列上的 [Key]
属性,它应该可以工作。如果需要保证唯一性,可以在其他列上创建唯一性索引。
我不会质疑您的模型为什么首先将这么多列标记为 [Key]。那并不能帮助您解决问题。此外,出于性能原因,您可能希望主键中包含所有这些列:在 EF 中使用代码优先时,主键默认创建为 clustered。
问题可能不是 number 个具有属性 [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-record-in-table-using-entity-framework?forum=adodotnetentityframework
我可以为您的问题想出两种解决方案:
如果您想坚持您的主键定义: 将您的 [order_timestamp] 截断为您的数据库接受的值。在 SQL 服务器的情况下,当截断到 10 毫秒时你会做得很好,C#:
order_timestamp = DateTime.Now.Truncate(TimeSpan.FromMilliseconds(10));
如果您不想截断时间戳但接受将 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)
希望对您有所帮助。
我正在尝试在一个函数中写入数据库中的两个表,该函数将上一页的列表作为参数。我调用数据库来检索 purchase_order_no,因为该列是在输入时生成的 IDENTITY 主键。
型号:
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; }
我在尝试将我的新 'purchase_order' 模型插入数据库时收到此错误:
Store update, insert, or delete statement affected an unexpected number of rows (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.
[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);
}
}
我认为问题出在您的模型中 class。在 purchase_order
中,为什么有这么多列标记为 [Key]
?由于 purchase_order_no
被声明为标识列,因此它本身应该是主键。我什至不知道为什么 EF 在启动时不抱怨,因为你的配置没有意义。
删除所有其他列上的 [Key]
属性,它应该可以工作。如果需要保证唯一性,可以在其他列上创建唯一性索引。
我不会质疑您的模型为什么首先将这么多列标记为 [Key]。那并不能帮助您解决问题。此外,出于性能原因,您可能希望主键中包含所有这些列:在 EF 中使用代码优先时,主键默认创建为 clustered。
问题可能不是 number 个具有属性 [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-record-in-table-using-entity-framework?forum=adodotnetentityframework
我可以为您的问题想出两种解决方案:
如果您想坚持您的主键定义: 将您的 [order_timestamp] 截断为您的数据库接受的值。在 SQL 服务器的情况下,当截断到 10 毫秒时你会做得很好,C#:
order_timestamp = DateTime.Now.Truncate(TimeSpan.FromMilliseconds(10));
如果您不想截断时间戳但接受将 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)
希望对您有所帮助。