C# A';必需的';无法通过“AddOrUpdate”更新集合字段`

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 {

我正在使用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 { 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
    f
    Id
    ,仍然得到了相同的错误,即
    详细信息
    字段为必填项。我可以在今天晚些时候(7小时后)查看此错误,并向您提供一份用于测试我的答案的.NET解决方案的副本。我的原始解决方案对我有效。您是否清理了数据库(删除表)在两次试验之间?无论如何,这是完整的项目:,使用branch
    SO34252506-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();