EF Core 多对多连接表,额外属性不起作用

问题描述

我想要这个连接表,它有 2 个外键,但还添加了一些其他属性:

[Serializable]
public class GroceryItemGroceryStore
{
    [Key,Column(Order = 0),Required]
    public int GroceryItemId { get; set; }
    [Key,Column(Order = 1),Required]
    public int GroceryStoreId { get; set; }

    public virtual GroceryItem GroceryItem { get; set; }
    public virtual GroceryStore GroceryStore { get; set; }

    [Required]
    public int NotInEstablishmentCount { get; set; }
    [Required]
    public int InEstablishmentCount { get; set; }
    [Required]
    public double Price { get; set; }
}

哪个加入这些实体:

public class GroceryItem : VeganItem<GroceryItemTag,GroceryStore>
{
    public GroceryItem(string name,string brand,string description,string image)
    {
        this.Name = name;
        this.Brand = brand;
        this.Description = description;
        this.Image = image;
    }

    [Required]
    public string Name { get; set; }
    [Required]
    public string Brand { get; set; }
    [Required]
    public string Description { get; set; }
    public string Image { get; set; }
    public virtual ICollection<GroceryItemGroceryStore> GroceryItemGroceryStores { get; set; }
}

[Serializable]
public abstract class VeganItem<VeganItemTagType,EstablishmentType>
{
    public int Id { get; set; }
    [Required]
    public int IsNotVeganCount { get; set; }
    [Required]
    public int IsVeganCount { get; set; }
    [Required]
    public int RatingsCount { get; set; }
    [Required]
    public int Rating { get; set; }
    [Required]
    public List<VeganItemTagType> Tags { get; set; }
    //[Required]
    public List<EstablishmentType> Establishments { get; set; }
    [Required]
    public int CurrentRevisionId { get; set; }
}

和这些实体:

[Serializable]
public class GroceryStore : Establishment<GroceryItem>
{
    public GroceryStore(string name,string placeId,string street,string suburb,string city,string streetNumber)
    {
        this.Name = name;
        this.PlaceId = placeId;
        this.Street = street;
        this.StreetNumber = streetNumber;
        this.City = city;
        this.Suburb = suburb;
    }
}

[Serializable]
public abstract class Establishment<VeganItemType>
{
    public int Id {get; set;}
    [Required]
    public string Name {get; set;}
    [Required]
    public string PlaceId {get; set;}
    [Required]
    public string Street {get; set;}
    public string Suburb {get; set;}
    public string City {get; set;}
    
    public List<VeganItemType> VeganItems {get; set;}
    public string StreetNumber {get; set;}
}

所以我尝试将我的连接表指定为在我的数据库上下文中定义多对多关系时要使用的表:


builder.Entity<GroceryItem>()
    .HasMany(p => p.Establishments)
    .WithMany(p => p.VeganItems)
    .UsingEntity(j => j.ToTable("GroceryItemGroceryStores"));   

  

有些地方不太对,因为我在运行 dotnet ef migrations add InitialCreate 时遇到了这个错误:

不能将表 'GroceryItemGroceryStores' 用于实体类型 'GroceryItemGroceryStore' 因为它用于实体类型 'GroceryItemGroceryStore (Dictionary)' 和潜在的 其他实体类型,但没有链接关系。添加一个 主键属性上“GroceryItemGroceryStore”的外键 并指向映射到的另一个实体的主键 'GroceryItemGroceryStores'。

我哪里出错了?

编辑 - 插入数据时出现问题
表已全部创建成功。但是,GroceryItemGroceryStores 表和 GroceryStores 表在插入了一个建立在其上的 GroceryItem 后没有得到任何插入。

以下是发送以添加 GroceryItem 的有效负载,该负载还应添加 GroceryStoreGroceryItemGroceryStore

{
    "name": "yummy fofod","brand": "goodfoobdgffe","description": "dfsad","establishments": [{
        "name": "Macdonalds","street": "Beach Rd","placeId": "fsadfsdfsdfsdfsadfsadfsdf"
    }],"tags": [
        {
            "name": "sdf","id": "9","iconCodePoint": 23145
        }
    ]
}

这是处理上述负载请求的控制器:

[HttpPost]
public async Task<ActionResult<GroceryItem>> PostGroceryItem(GroceryItem groceryItem)
{
    _context.GroceryItems.Add(groceryItem);
    await _context.SaveChangesAsync();

    return CreatedAtAction("GetGroceryItem",new { id = groceryItem.Id },groceryItem);
}

解决方法

存在以下两个属性-

public virtual GroceryItem GroceryItem { get; set; }
public virtual GroceryStore GroceryStore { get; set; }

GroceryItemGroceryStore 模型中已经通过连接实体 GroceryItemGroceryStoreGroceryItemGroceryStore 置于多对多关系中。

然后您的关系配置代码尝试在它们之间创建新的多对多关系,但尝试使用相同的连接实体。这就是问题所在,而这正是错误消息所说的内容。

删除配置代码,它应该会自动工作。

如果要手动配置关系,则将其更改为-

builder.Entity<GroceryItemGroceryStore>()
    .HasOne(p => p.GroceryItem)
    .WithMany(p => p.GroceryItemGroceryStores)
    .HasForeignKey(p=> p.GroceryItemId);
    
builder.Entity<GroceryItemGroceryStore>()
    .HasOne(p => p.GroceryStore)
    .WithMany()
    .HasForeignKey(p=> p.GroceryStoreId);

或者,最好添加以下属性 -

public virtual ICollection<GroceryItemGroceryStore> GroceryItemGroceryStores { get; set; }

GroceryStore 模型,并将配置更改为 -

builder.Entity<GroceryItemGroceryStore>()
    .HasOne(p => p.GroceryItem)
    .WithMany(p => p.GroceryItemGroceryStores)
    .HasForeignKey(p=> p.GroceryItemId);
    
builder.Entity<GroceryItemGroceryStore>()
    .HasOne(p => p.GroceryStore)
    .WithMany(p=> p.GroceryItemGroceryStores)
    .HasForeignKey(p=> p.GroceryStoreId);

编辑:
您应该从 Establishments 模型中删除 VeganItem 属性,并从 VeganItems 模型中删除 Establishment 属性。否则,它们将通过单独的连接表创建单独的多对多关系。

编辑 - 用于插入数据
请按照以下步骤操作 -

  1. 从您的负载创建一个新的 GroceryStore(例如 newStore
  2. 将其插入数据库
  3. 从负载创建一个新的 GroceryItem(例如 newItem
  4. 执行以下操作 -
newItem.GroceryItemGroceryStores = new List<GroceryItemGroceryStore>
{
    new GroceryItemGroceryStore { GroceryStoreId = newStore.Id }
};

_context.GroceryItems.Add(newItem);
await _context.SaveChangesAsync();

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...