我已经开始使用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个表,为每个用户收集禁用成分和首选成分。我应该怎么做才能使其正常工作?
答案 0 :(得分:1)
您的数据库关系设计错误。您应该向Ingredient
添加更多字段以指出Forbidden
或Preferred
(tinyint
类型)。
答案 1 :(得分:1)
您必须规范化数据库。第一个表保留一个具有主键UserId的User,第二个表-Ingridient将IngridientId用作主键,第三个表UserIngridient会将UserId和Ingridient Id保留为外键。所有要素都相同,可能其中只有一部分禁止用户使用,但另一名用户则不禁止。因此,您需要第四张表-类型。但是由于只有两种类型,因此可以为此使用标志-禁止或优先。此标志应保留在UserIngridient表中,因为它取决于用户和该用户的本机。
将代码更改为此:
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
}
答案 2 :(得分:0)
回答有关同一表的多个外键的原始问题。正在通过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();
}
}
}