EF Core 多对多连接 Table,额外属性不起作用
EF Core Many to Many Join Table with Extra Properties Not Working
我想要这个连接 table,它有 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;}
}
所以我尝试将我的连接 table 指定为 table 以在我的数据库上下文中定义我的多对多关系时使用:
builder.Entity<GroceryItem>()
.HasMany(p => p.Establishments)
.WithMany(p => p.VeganItems)
.UsingEntity(j => j.ToTable("GroceryItemGroceryStores"));
有些不对劲,因为我在 运行 dotnet ef migrations add InitialCreate
:
时收到此错误
Cannot use table 'GroceryItemGroceryStores' for entity type
'GroceryItemGroceryStore' since it is being used for entity type
'GroceryItemGroceryStore (Dictionary<string, object>)' and potentially
other entity types, but there is no linking relationship. Add a
foreign key to 'GroceryItemGroceryStore' on the primary key properties
and pointing to the primary key on another entity typed mapped to
'GroceryItemGroceryStores'.
我哪里错了?
编辑 - 插入数据时出现问题
table 已全部创建成功。但是,GroceryItemGroceryStores
table 和 GroceryStores
table 在插入一个已建立的 GroceryItem
后没有得到任何插入。
以下是发送的有效载荷以添加 GroceryItem
,其中还应添加 GroceryStore
和 GroceryItemGroceryStore
:
{
"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
模型中已经通过连接实体GroceryItemGroceryStore
.
将GroceryItem
和GroceryStore
置于多对多关系中
那么你的关系配置代码试图在它们之间创建一个新的多对多关系,但试图使用相同的连接实体。这就是问题所在,这正是错误消息所说的内容。
删除配置代码,它应该会自动运行。
如果要手动配置关系,则改为-
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);
编辑:
您应该从 VeganItem
模型中删除 Establishments
属性 并从 Establishment
模型中删除 VeganItems
属性。否则,他们将通过单独的连接创建一个单独的多对多关系 table.
编辑 - 用于插入数据
按照以下步骤操作 -
- 从您的负载
创建一个新的GroceryStore
(例如newStore
)
- 将其插入数据库
- 从有效负载
创建一个新的GroceryItem
(例如newItem
)
- 执行以下操作 -
newItem.GroceryItemGroceryStores = new List<GroceryItemGroceryStore>
{
new GroceryItemGroceryStore { GroceryStoreId = newStore.Id }
};
_context.GroceryItems.Add(newItem);
await _context.SaveChangesAsync();
我想要这个连接 table,它有 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;}
}
所以我尝试将我的连接 table 指定为 table 以在我的数据库上下文中定义我的多对多关系时使用:
builder.Entity<GroceryItem>()
.HasMany(p => p.Establishments)
.WithMany(p => p.VeganItems)
.UsingEntity(j => j.ToTable("GroceryItemGroceryStores"));
有些不对劲,因为我在 运行 dotnet ef migrations add InitialCreate
:
Cannot use table 'GroceryItemGroceryStores' for entity type 'GroceryItemGroceryStore' since it is being used for entity type 'GroceryItemGroceryStore (Dictionary<string, object>)' and potentially other entity types, but there is no linking relationship. Add a foreign key to 'GroceryItemGroceryStore' on the primary key properties and pointing to the primary key on another entity typed mapped to 'GroceryItemGroceryStores'.
我哪里错了?
编辑 - 插入数据时出现问题
table 已全部创建成功。但是,GroceryItemGroceryStores
table 和 GroceryStores
table 在插入一个已建立的 GroceryItem
后没有得到任何插入。
以下是发送的有效载荷以添加 GroceryItem
,其中还应添加 GroceryStore
和 GroceryItemGroceryStore
:
{
"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
模型中已经通过连接实体GroceryItemGroceryStore
.
GroceryItem
和GroceryStore
置于多对多关系中
那么你的关系配置代码试图在它们之间创建一个新的多对多关系,但试图使用相同的连接实体。这就是问题所在,这正是错误消息所说的内容。
删除配置代码,它应该会自动运行。
如果要手动配置关系,则改为-
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);
编辑:
您应该从 VeganItem
模型中删除 Establishments
属性 并从 Establishment
模型中删除 VeganItems
属性。否则,他们将通过单独的连接创建一个单独的多对多关系 table.
编辑 - 用于插入数据
按照以下步骤操作 -
- 从您的负载 创建一个新的
- 将其插入数据库
- 从有效负载 创建一个新的
- 执行以下操作 -
GroceryStore
(例如newStore
)
GroceryItem
(例如newItem
)
newItem.GroceryItemGroceryStores = new List<GroceryItemGroceryStore>
{
new GroceryItemGroceryStore { GroceryStoreId = newStore.Id }
};
_context.GroceryItems.Add(newItem);
await _context.SaveChangesAsync();