C# A';必需的';无法通过“AddOrUpdate”更新集合字段`
我正在使用Asp.net web api 2+实体框架6 基本上我有两种型号:C# A';必需的';无法通过“AddOrUpdate”更新集合字段`,c#,asp.net-mvc,entity-framework,asp.net-web-api,C#,Asp.net Mvc,Entity Framework,Asp.net Web Api,我正在使用Asp.net web api 2+实体框架6 基本上我有两种型号: public class MyOrderModel { public int Id { get; set; } public string OrderNumber { get; set;} public string AuthCode { get; set; } [Required] public List<MyOrderDetailModel> Details {
public class MyOrderModel
{
public int Id { get; set; }
public string OrderNumber { get; set;}
public string AuthCode { get; set; }
[Required]
public List<MyOrderDetailModel> Details { get; set; }
}
public class MyOrderDetailModel
{
public int Id { get; set; }
public decimal Amount{ get; set;}
}
在第一个(初始)updatedatabase
命令之后,一切都很好,我可以看到上面的数据保存到database2表中
稍后,我想将AuthCode
属性值从ABCDE
更新为ABCDEXXX
,
唯一的变化是赋值:
context.MyOrderModels.AddOrUpdate(
s => s.OrderNumber,
new MyOrderModel
{
OrderNumber = "0001",
// THE ONLY CHANGE!
AuthCode = "ABCDEXXX",
Details = new List<MyOrderDetailModel>()
{
new MyOrderDetailModel()
{
Amount = 5.67M
}
}
};
context.MyOrderModels.AddOrUpdate(
s=>s.OrderNumber,
新MyOrderModel
{
OrderNumber=“0001”,
//唯一的改变!
AuthCode=“ABCDEXXX”,
详细信息=新列表()
{
新的MyOrderDetailModel()
{
金额=567万
}
}
};
我希望EntityFramework通过搜索OrderNumber
上的条件,在数据库中找到目标数据行,然后更新AuthCode
,但现在我在Seed
函数中总是遇到这个异常:
实体验证失败-错误如下:
MyTest.Models.MyOrderModel验证失败
- 详细信息:详细信息字段是必需的
显然,该值是为字段
详细信息提供的,所以我遗漏了什么?问题在于PostPayQRCodeFuelOrderModel
的Id
字段。在您的环境中,数据库将该字段用作标识(主键)字段,并希望自己生成该值
在您的情况下,有一个简单的解决方法:
context.MyOrderModel.AddOrUpdate(
p => p.OrderNumber,
new PostPayQRCodeFuelOrderModel
{
OrderNumber = "00001",
Details = new List<MyOrderDetailModel>()
{
new MyOrderDetailModel()
{
Amount = 5.67M
}
}
}
);
然后,您需要重新创建MyOrderModel
表。注意:添加迁移只是为了修改Id
字段的通常方法不起作用,您需要重新创建表
多次运行种子是有效的,也就是说,没有重复的(只是自己检查)
更新2:
我没有一个完整的解释,为什么您的代码不工作,但是使用下面的代码,您应该可以按照自己的意愿构建数据库对象的创建和更新
此代码可以在Seed()中多次运行而不会重复。当然,AuthCode
的更新是人为的,但我的观点是将创建和更新分开(以防在最终实现中需要分开)
整个项目在分支机构SO34252506-1中提供
代码如下:
var mom = context.MyOrderModel.Where(m => m.OrderNumber == "00001").FirstOrDefault();
if (mom == null)
{
mom = new PostPayQRCodeFuelOrderModel
{
OrderNumber = "00001",
AuthCode = "ABCDE",
Details = new List<MyOrderDetailModel>() {
new MyOrderDetailModel
{
Amount = 5.67M
}
}
};
context.MyOrderModel.AddOrUpdate(p => p.OrderNumber, mom);
context.SaveChanges();
}
mom.AuthCode = "ABCDEXXX";
context.SaveChanges();
更新4:
如果这仍然不起作用,则删除数据库,但另外重新创建迁移:
删除现有迁移
不要让EF假设它知道数据库的状态,而是强制它从头开始创建迁移(请参阅其他SO问题以获取建议)。但是,在这样做之前,请注意此操作很可能会覆盖Seed()
也可以运行,因此在操作之前,请复制该文件
为什么我不能使用Id
作为主键?您也可以使用它作为主键,但我阅读了您的问题,以便您能够明确定义Id
值。这是可能的,请参阅上面的更新。我已经通过引用您的第一段代码进行了测试,将选择器改为OrderNumber
fId
,仍然得到了相同的错误,即详细信息
字段为必填项。我可以在今天晚些时候(7小时后)查看此错误,并向您提供一份用于测试我的答案的.NET解决方案的副本。我的原始解决方案对我有效。您是否清理了数据库(删除表)在两次试验之间?无论如何,这是完整的项目:,使用branchSO34252506-1
。
public class MyOrderModel
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
var mom = context.MyOrderModel.Where(m => m.OrderNumber == "00001").FirstOrDefault();
if (mom == null)
{
mom = new PostPayQRCodeFuelOrderModel
{
OrderNumber = "00001",
AuthCode = "ABCDE",
Details = new List<MyOrderDetailModel>() {
new MyOrderDetailModel
{
Amount = 5.67M
}
}
};
context.MyOrderModel.AddOrUpdate(p => p.OrderNumber, mom);
context.SaveChanges();
}
mom.AuthCode = "ABCDEXXX";
context.SaveChanges();
var mom = context.MyOrderModel.Where(m => m.OrderNumber == "00001").Include(m => m.Details).FirstOrDefault();