[英]Entity Framework Core: many-to-many relationship with the same object
我已經開始使用 Entity Framework Core。 我有一個User
實體:
public class UserEntity
{
public UserEntity()
{
ForbiddenIngredients = new HashSet<Ingredient>();
PreferredIngredients = new HashSet<Ingredient>();
}
[Key]
public string ID { get; set; }
public string Email { get; set; } //UserName
public string FullName { get; set; }
public virtual ICollection<Ingredient> ForbiddenIngredients { get; set; }
public virtual ICollection<Ingredient> PreferredIngredients { get; set; }
}
我還有Ingredient
實體:
public class Ingredient
{
[Key]
public string IngredientID { get; set; }
[Required]
public string Name { get; set; }
}
如您所見,我想創建 2 個表,為每個用戶收集禁用成分和首選成分。 我應該怎么做才能使它工作?
你的數據庫關系設計是錯誤的。 您應該向Ingredient
添加更多字段以指出Forbidden
或Preferred
( tinyint
類型)。
您必須標准化您的數據庫。 第一個表保留一個帶有主鍵 UserId 的用戶,第二個表 - Ingridient 將 IngridientId 作為主鍵,第三個表 UserIngridient 將保留 UserId 和 Ingridient Id 作為外鍵。 所有成分都是相同的,只有其中一些可能被用戶禁止,但可能不會被其他用戶禁止。 所以你需要第四個表 - 類型。 但是由於您只有 2 種類型,因此您可以為此使用標志 - 禁止或首選。 此標志應保留在 UserIngridient 表中,因為它取決於用戶和該用戶的 ingridient。
將您的代碼更改為:
public class User
{
public User()
{
Ingredients = new HashSet<Ingredient>();
}
[Key]
public string ID { get; set; }
public string Email { get; set; } //UserName
public string FullName { get; set; }
public virtual ICollection<Ingredient> Ingredients { get; set; }
}
public class Ingredient
{
[Key]
public int ID { get; set; }
[Required]
public string Name { get; set; }
}
並且您必須再添加一張表以進行規范化:
public class UserIngredient
{
[Key]
public int ID { get; set; }
public int UserID { get; set; }
public int IngredientID { get; set; }
public int IngredientTypeId { get; set; } // 0 or 1
// OR public string IngredientType { get; set; } // Forb or Pref
.... add some virtual props here
}
回答關於同一個表的多個外鍵的原始問題。 正在通過 Fluent API 在DbContext.OnModelConfiguring
中設置邏輯。
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
namespace ConsoleApp3
{
public class User
{
public User()
{
ForbiddenIngredients = new HashSet<Ingredient>();
PreferredIngredients = new HashSet<Ingredient>();
}
[Key]
public string ID { get; set; }
public string Email { get; set; }
public string FullName { get; set; }
public virtual ICollection<Ingredient> ForbiddenIngredients { get; set; }
public virtual ICollection<Ingredient> PreferredIngredients { get; set; }
}
public class Ingredient
{
[Key]
public int IngredientID { get; set; }
[Required]
public string Name { get; set; }
public virtual User ForbiddenUser { get; set; }
public string ForbiddenUserId { get; set; }
public virtual User PreferredUser { get; set; }
public string PreferredUserId { get; set; }
}
public class AppDbContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Ingredient> Ingredients { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("connection string");
base.OnConfiguring(optionsBuilder);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<User>()
.HasMany(x => x.PreferredIngredients)
.WithOne(x => x.PreferredUser)
.HasForeignKey(x => x.PreferredUserId);
modelBuilder.Entity<User>()
.HasMany(x => x.ForbiddenIngredients)
.WithOne(x => x.ForbiddenUser)
.HasForeignKey(x => x.ForbiddenUserId);
base.OnModelCreating(modelBuilder);
}
}
class Program
{
static void Main(string[] args)
{
var user = new User()
{
Email = "test@test.com",
ID = Guid.NewGuid().ToString(),
FullName = "name",
};
user.ForbiddenIngredients.Add(new Ingredient()
{
ForbiddenUser = user,
Name = "forbidden",
});
user.PreferredIngredients.Add(new Ingredient()
{
PreferredUser = user,
Name = "preferred",
});
var dbContext = new AppDbContext();
dbContext.Add(user);
dbContext.SaveChanges();
var dbUser = dbContext.Users
.Include(x => x.ForbiddenIngredients)
.Include(x => x.PreferredIngredients)
.FirstOrDefault();
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.