我正在尝试在一个函数中写入数据库中的两个表,该函数将列表作为上一页的参数。我调用db来检索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”模型插入db:
时收到此错误存储更新,插入或删除语句会影响意外的行数(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);
}
}
答案 0 :(得分:1)
我认为问题出在您的模型类中。在purchase_order
中,为什么有这么多列标记为[Key]
?由于purchase_order_no
被声明为标识列,因此它本身应该是主键。我甚至都不知道为什么EF在启动时没有抱怨,因为你的配置毫无意义。
删除所有其他列上的[Key]
属性,它应该可以正常工作。如果需要确保唯一性,可以在其他列上创建唯一索引。
答案 1 :(得分:0)
我不会对您的模型提出疑问,为什么您会首先拥有如此多的列标记为[Key]的列。那无助于您解决问题。此外,出于性能方面的考虑,您可能希望主键中包含所有这些列:当首先将代码与EF一起使用时,默认情况下主键被创建为 clustered 。
问题可能是不是具有属性[Key]的列的 number 。在主键中只合并了一个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 Server,则在将其截断为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)
我希望这会有所帮助。