我使用实体框架迁移(在自动迁移模式下)。一切都很好,但是我有一个问题:

有多对多关系时应如何播种数据?

例如,我有两个模型类:

public class Parcel
{
    public int Id { get; set; }
    public string Description { get; set; }
    public double Weight { get; set; }
    public virtual ICollection<BuyingItem> Items { get; set; }
}

public class BuyingItem
{
    public int Id { get; set; }
    public decimal Price { get; set; }
    public virtual ICollection<Parcel> Parcels { get; set; }
}


我了解如何播种简单数据(用于PaymentSystem类)和一对多关系,但是我应该在Seed方法中编写什么代码来生成ParcelBuyingItem的某些实例?我的意思是使用DbContext.AddOrUpdate(),因为我不想每次运行Update-Database时都重复数据。

protected override void Seed(ParcelDbContext context)
{
    context.AddOrUpdate(ps => ps.Id,
        new PaymentSystem { Id = 1, Name = "Visa" },
        new PaymentSystem { Id = 2, Name = "PayPal" },
        new PaymentSystem { Id = 3, Name = "Cash" });
}




protected override void Seed(Context context)
{
    base.Seed(context);

    // This will create Parcel, BuyingItems and relations only once
    context.AddOrUpdate(new Parcel()
    {
        Id = 1,
        Description = "Test",
        Items = new List<BuyingItem>
        {
            new BuyingItem() { Id = 1, Price = 10M },
            new BuyingItem() { Id = 2, Price = 20M }
        }
    });

    context.SaveChanges();
}


这段代码创建了ParcelBuyingItems及其关系,但是如果我在另一个BuyingItem中需要相同的Parcel(它们之间存在多对多关系),我会在第二个包裹中重复此代码-将在数据库中复制BuyingItems(尽管我设置了相同的Id)。

例:

protected override void Seed(Context context)
{
    base.Seed(context);

    context.AddOrUpdate(new Parcel()
    {
        Id = 1,
        Description = "Test",
        Items = new List<BuyingItem>
        {
            new BuyingItem() { Id = 1, Price = 10M },
            new BuyingItem() { Id = 2, Price = 20M }
        }
    });

    context.AddOrUpdate(new Parcel()
    {
        Id = 2,
        Description = "Test2",
        Items = new List<BuyingItem>
        {
            new BuyingItem() { Id = 1, Price = 10M },
            new BuyingItem() { Id = 2, Price = 20M }
        }
    });

    context.SaveChanges();
}


如何在不同的BuyingItem中添加相同的Parcel

最佳答案

您必须以与在任何EF代码中建立多对多关系相同的方式填充多对多关系:

protected override void Seed(Context context)
{
    base.Seed(context);

    // This will create Parcel, BuyingItems and relations only once
    context.AddOrUpdate(new Parcel()
    {
        Id = 1,
        Description = "Test",
        Items = new List<BuyingItem>
        {
            new BuyingItem() { Id = 1, Price = 10M },
            new BuyingItem() { Id = 2, Price = 20M }
        }
    });

    context.SaveChanges();
}


指定将在数据库中使用的Id是至关重要的,否则每个Update-Database都会创建新记录。

AddOrUpdate不支持以任何方式更改关系,因此您不能在下一次迁移中使用它来添加或删除关系。如果需要,您必须手动删除关联,方法是将Parcel装入BuyingItems并在导航集合上调用RemoveAdd来中断或添加新的关联。

07-24 09:50
查看更多