MVC EntityFramework 代码优先迁移 - Seed() 因 DbUpdateException 而失败?

MVC EntityFramework Code-First Migrations - Seed() Failing with DbUpdateException?

我正在开发一个有点简单的 InventoryTracker MVC5 应用程序,其中我在将 LocalDatabase 设置为 Seed().

时遇到了一些问题

当我在下面的代码上运行 update-database 命令时,在 context.INV_Types.AddRange(invTypes) 行出现如下异常:

An exception of type 'System.Data.Entity.Infrastructure.DbUpdateException' occurred in EntityFramework.dll but was not handled in user code. Additional information: An error occurred while updating the entries. See the inner exception for details.

内部异常The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value.\r\nThe statement has been terminated.


代码:

internal sealed class Configuration : DbMigrationsConfiguration<InventoryTracker.DAL.InventoryTrackerContext>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = false;
    }

    protected override void Seed(InventoryTracker.DAL.InventoryTrackerContext context)
    {
        if (System.Diagnostics.Debugger.IsAttached == false)
        {
            System.Diagnostics.Debugger.Launch();
        }

        List<INV_Locations> invLocs = getLocations();
        context.INV_Locations.AddRange(invLocs);
        List<INV_Manufacturers> invManufacturers = getManufacturers();
        context.INV_Manufacturers.AddRange(invManufacturers);
        List<INV_Models> invModels = getModels();
        context.INV_Models.AddRange(invModels);
        List<INV_Statuses> invStatuses = getStatuses();
        context.INV_Statuses.AddRange(invStatuses);
        List<INV_Types> invTypes = getTypes();
        context.INV_Types.AddRange(invTypes); // EXCEPTION?
        List<INV_Vendors> invVendors = getVendors();
        context.INV_Vendors.AddRange(invVendors);

        context.SaveChanges(); // Was told I needed to Save the other seeds before the Assets to ensure primary keys are created in the other tables?

        List<INV_Assets> invAssets = getAssets();
        context.INV_Assets.AddRange(invAssets);

        context.SaveChanges();
    }

    private List<INV_Types> getTypes()
    {
        List<INV_Types> testTypes = new List<INV_Types>
        {
            new INV_Types
            {
                Id = 1,
                type_description = "Server",
                created_by = "Admin",
                created_date = DateTime.Now
            },
            new INV_Types
            {
                Id = 2,
                type_description = "IP Phone",
                created_by = "Admin",
                created_date = DateTime.Now
            },
            new INV_Types
            {
                Id = 3,
                type_description = "Monitor",
                created_by = "Admin",
                created_date = DateTime.Now
            }
        };
        return testTypes;
    }

    private List<INV_Assets> getAssets()
        {
            List<INV_Assets> testAssets = new List<INV_Assets>
            {
              new INV_Assets
              {
                Id = 1,
                ip_address = "10.10.135.38",
                mac_address = "10.10.177.44",
                note = "",
                owner = "John Smith",
                cost = 35,
                po_number = "G348",
                invoice_number = 1447,
                serial_number = "JX14582Y",
                asset_tag_number = "293548195023",
                //acquired_date = Convert.ToDateTime(10212014),
                acquired_date = DateTime.ParseExact("10212014", "MMddyyyy", CultureInfo.InvariantCulture),
                disposed_date = null,
                created_by = "Admin",
                created_date = DateTime.Now,
                Location_Id = 1,
                Manufacturer_Id = 1,
                Model_Id = 1,
                Status_Id = 2,
                Type_Id = 3,
                Vendor_Id = 3
            }
        };
        return testAssets;
    }

有没有人知道我的 Seed() for INV_Types 的结构中可能导致此问题的原因?

我认为我可能需要在 getTYpes() 之前保存对上下文的更改,但在 .AddRange(invStatuses) 之后添加 context.SaveChanges() 只会导致相同的错误那个新 context.SaveChanges()??

我在下面包含了我的其他种子方法,以在有人看到我忽略的内容时提供帮助:

    #region Seed Locations
    private List<INV_Locations> getLocations()
    {
        List<INV_Locations> testLocations = new List<INV_Locations>
        {
            new INV_Locations
            {
                Id = 1,
                location_dept = "IT",
                location_room = "Server",
                created_by = "Admin",
                created_date = DateTime.Now
            },
            new INV_Locations
            {
                Id = 2,
                location_dept = "Break Room",
                location_room = "Kitchen",
                created_by = "Admin",
                created_date = DateTime.Now
            },
            new INV_Locations
            {
                Id = 3,
                location_dept = "Accounting",
                location_room = "Conference",
                created_by = "Admin",
                created_date = DateTime.Now
            }
        };
        return testLocations;
    }
    #endregion

    #region Seed Manufacturers
    private List<INV_Manufacturers> getManufacturers()
    {
        List<INV_Manufacturers> testManufacturers = new List<INV_Manufacturers>
        {
            new INV_Manufacturers
            {
                Id = 1,
                manufacturer_description = "Samsung",
                created_by = "Admin",
                created_date = DateTime.Now
            },
            new INV_Manufacturers
            {
                Id = 2,
                manufacturer_description = "MITEL",
                created_by = "Admin",
                created_date = DateTime.Now
            },
            new INV_Manufacturers
            {
                Id = 3,
                manufacturer_description = "Oracle",
                created_by = "Admin",
                created_date = DateTime.Now
            }
        };
        return testManufacturers;
    }
    #endregion

    #region Seed Models
    private List<INV_Models> getModels()
    {
        List<INV_Models> testModels = new List<INV_Models>
        {
            new INV_Models
            {
                Id = 1,
                model_description = "XTERAV12",
                created_by = "Admin",
                created_date = DateTime.Now
            },
            new INV_Models
            {
                Id = 2,
                model_description = "5330",
                created_by = "Admin",
                created_date = DateTime.Now
            },
            new INV_Models
            {
                Id = 3,
                model_description = "Sunblade 6000",
                created_by = "Admin",
                created_date = DateTime.Now
            }
        };
        return testModels;
    }
    #endregion

    #region Seed Statuses
    private List<INV_Statuses> getStatuses()
    {
        List<INV_Statuses> testStatuses = new List<INV_Statuses>
        {
            new INV_Statuses
            {
                Id = 1,
                status_description = "AVAILABLE",
                created_by = "Admin",
                created_date = DateTime.Now
            },
            new INV_Statuses
            {
                Id = 2,
                status_description = "SIGNEDOUT",
                created_by = "Admin",
                created_date = DateTime.Now
            },
            new INV_Statuses
            {
                Id = 3,
                status_description = "RECYCLED",
                created_by = "Admin",
                created_date = DateTime.Now
            },
            new INV_Statuses
            {
                Id = 4,
                status_description = "AUCTIONED",
                created_by = "Admin",
                created_date = DateTime.Now
            }
        };
        return testStatuses;
    }
    #endregion

    #region Seed Types
    private List<INV_Types> getTypes()
    {
        List<INV_Types> testTypes = new List<INV_Types>
        {
            new INV_Types
            {
                Id = 1,
                type_description = "Server",
                created_by = "Admin",
                created_date = DateTime.Now
            },
            new INV_Types
            {
                Id = 2,
                type_description = "IP Phone",
                created_by = "Admin",
                created_date = DateTime.Now
            },
            new INV_Types
            {
                Id = 3,
                type_description = "Monitor",
                created_by = "Admin",
                created_date = DateTime.Now
            }
        };
        return testTypes;
    }
    #endregion

    #region Seed Vendors
    private List<INV_Vendors> getVendors()
    {
        List<INV_Vendors> testVendors = new List<INV_Vendors>
        {
            new INV_Vendors
            {
                Id = 1,
                vendor_name = "Oracle",
                created_by = "Admin",
                created_date = DateTime.Now
            },
            new INV_Vendors
            {
                Id = 2,
                vendor_name = "Centriq",
                created_by = "Admin",
                created_date = DateTime.Now
            },
            new INV_Vendors
            {
                Id = 3,
                vendor_name = "Samsung",
                created_by = "Admin",
                created_date = DateTime.Now
            }
        };
        return testVendors;
    }
    #endregion

编辑:

正如 IronMan84 指出的那样,我错误地复制粘贴到了每个实体的多个实例都具有相同 Id 值的位置(例如 1、2、1 而不是 1, 2, 3).但是,错误仍然存​​在,除了现在在以下行:

        context.INV_Vendors.AddRange(invVendors);

        context.SaveChanges(); // DbUpdateException!

        List<INV_Assets> invAssets = getAssets();

EDIT2:向最初列出的错误添加了 内部异常 详细信息。 The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value.\r\nThe statement has been terminated.

EDIT3:为了更好地诊断问题,我尝试在每个 .AddRange() 调用之后添加 context.SaveChanges(),但是 [= 之后的第一个实例20=] 导致相同的错误:

An exception of type 'System.Data.Entity.Infrastructure.DbUpdateException' occurred in EntityFramework.dll but was not handled in user code. Additional information: An error occurred while updating the entries. See the inner exception for details.

内部异常The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value.\r\nThe statement has been terminated.

我只能想象这是在引用我的 getLocations()[created_date] 值设置为 DateTime.Now,但我不确定问题出在哪里?

在我的模型中,我将属性定义为:

    [Required]
    [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
    public DateTime created_date { get; set; }

您的 getTypes() 方法中的 2 个类型的 Id 值为 1。EF 不喜欢这种冲突,因此会爆炸。

编辑:您在评论中提到的错误 (The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value.\r\nThe statement has been terminated.) 仅由具有 DateTime 属性 的对象引起,其当前值设置为日期在 1753 年 1 月 1 日之前(很可能设置为 DateTime.MinValue,即 1/1/0001)。

造成这种情况的原因是 EF 将 C# 的 DateTime 类型映射到 SQL 的 datetime 类型(与 datetime2 相对,后者可以返回到 1/ 1/0001),它有上面提到的最低日期要求。当您尝试保存日期为 before 的对象时 1/1/1753 SQL 认为您正在尝试将 datetime2 保存在列中datetime 类型并爆炸。

解决方案是对其进行调试,找出哪些记录的属性仍设置为错误日期(如 DateTime.MinValue),然后调整代码以相应地编辑这些属性。