C# 关系数据库:数据库结构/流程

C# 关系数据库:数据库结构/流程,c#,sql-server,database,entity-framework-core,C#,Sql Server,Database,Entity Framework Core,我正在使用实体框架来设置数据库。我是关系数据库的新手,我正在尝试确定设置一些表及其关系的正确方法。这是独家新闻 假设我的数据库中有三个表 主表是表A,它包含一个对象的数据集,我们称这个对象为食物。列:FoodID主键,RecipeID外键与表C中的配方配对 表C:包含用于制作表A中存储的不同食品的配方记录。列:RecipeID主键和配方名称 表B:是创建食品的说明/食谱条目。列:EntryID主键,RecipeID外键引用表C中的配方ID,FoodID外键引用表a中的食品 我不能用正确的方法来做

我正在使用实体框架来设置数据库。我是关系数据库的新手,我正在尝试确定设置一些表及其关系的正确方法。这是独家新闻

假设我的数据库中有三个表

主表是表A,它包含一个对象的数据集,我们称这个对象为食物。列:FoodID主键,RecipeID外键与表C中的配方配对

表C:包含用于制作表A中存储的不同食品的配方记录。列:RecipeID主键和配方名称

表B:是创建食品的说明/食谱条目。列:EntryID主键,RecipeID外键引用表C中的配方ID,FoodID外键引用表a中的食品

我不能用正确的方法来做这件事,因为这是一种循环关系

我只是从食物表中删除外键RecipeID吗?在这种情况下,我应该追求什么样的正确流程

 Recipes -> Multiple Recipe Entries -> Food -> Recipe
食物需要一个食谱来制作,但食谱中的食物用于制作其他食物

将数据概念化为C代码看起来是这样的

public class Food
{
    public int FoodID { get; set; }
    public string Name { get; set; }
    public List<Food> Recipe { get; set; }
}
实体框架模型如下所示

public class Food
{
    [Key]
    public int FoodID { get; set; }//Pri Key
    public string Name { get; set; }
    public int FoodRecipeID { get; set; }//Foreign Key

    public virtual FoodRecipe FoodRecipe { get; set; }//Navigation Property
}

public class FoodRecipeEntry
{
    [Key] 
    public int FoodRecipeEntryId { get; set; } //Pri Key
    public string Name { get; set; }
    public int FoodID { get; set; }//Foreign Key
    public int FoodRecipeID { get; set; }

    //Navigation Properties
    public Food Food { get; set; }
    public FoodRecipe FoodRecipe { get; set; }
}

public class FoodRecipe
{
    [Key]
    public int FoodRecipeID { get; set; } //Pri Key
    public string Name { get; set; }
    public virtual ICollection<FoodRecipeEntry> FoodRecipeEntries {get; set; }//Navigation Property
}

以下是一些要点:

从FoodRecipeEntry中删除食品ID,FoodID由配方暗示,因为配方是针对特定食品的,并且条目属于给定配方 我个人会把外键放在菜谱里面,而不是食物里面——一种食物可能有多个菜谱,所以它应该是菜谱->食物 在代码中,这看起来是这样的:

公共食品 { [关键] public int FoodID{get;set;}//Pri Key 公共字符串名称{get;set;} 公共虚拟FoodRecipe FoodRecipe{get;set;}//导航属性 } 公共级餐饮 { [关键] public int FoodRecipeEntryId{get;set;}//Pri Key 公共字符串名称{get;set;} [ForeignKeyFoodRecipe]//就我个人而言,我更喜欢使用显式外键属性来避免隐式Jankines public int FoodRecipeID{get;set;} [外国成分] public int IngredientID{get;set;} //导航属性 公共虚拟FoodRecipe FoodRecipe{get;set;} 公共虚拟食品配料{get;set;} } 公共级餐饮 { [关键] public int FoodRecipeID{get;set;}//Pri Key 公共字符串名称{get;set;} [ForeignKeyFood]//就我个人而言,我更喜欢使用显式外键属性来避免隐含的刺耳 public int{get;set;}//外键 公共虚拟食品{get;set;} 公共虚拟ICollection FoodRecipeEntries{get;set;}//导航属性 }
循环关系有什么问题?这听起来很适合你的情况。你只需要确保你的UI不允许你创建无限循环。我相信你的模型在概念上是正确的-你为什么要质疑它?我并没有假设它是错误的,我只是想知道这种结构的首选或普遍接受的方法是什么。就像我说的,我是数据库的新手。我很欣赏这些评论。我假设有些食物是初级/基本食物,没有配方,在这种情况下,FoodRecipientry肯定需要FoodID属性。我想你可能没有注意到,一种食物可以有一个配方来制作,但是可能是食谱中许多食物中的一种——因此我认为原始的关键点是正确的。这是公平的@DaleK,尽管上面确实没有指定,如果是,我会将该字段称为IngredenId和配料,这样就不会产生误导。即使在那时,上面的结构仍然可以避免循环引用问题,这是一个更好的理由,不在食物对象上有配方ID。撇开命名不谈,我认为循环引用是必需的,并且是可以的。注意,使用像int这样的可空值?对于另一端可能没有实体的外键:。