如何先在代码中保存外键集合
How to save collection of foreign keys in code first
更新: 目前我只能将一种产品分配给 Recipe。我想要做的是在配方(控制器创建)中添加对数据库中所有产品的访问权限 - 这里我使用 public int ProductId 但它只允许保存一个产品。我想从此列表中选择一些产品并将外键保存在数据库中。 photo
我也尝试在 ProductId 中添加 public List < int > 但我从 entity framework.
中收到错误
如有任何帮助,我将不胜感激。
public class Recipe
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public int ProductId { get; set; }
public List<Product> Products { get; set; }
public Recipe()
{
this.Products = new List<Product>();
}
}
public class Product
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public Recipe? Recipes { get; set; }
}
如果你想创建一个 one-to-many 关系,你几乎是在正确的方向,但你应该删除 public int ProductId { get; set; }
和 re-arrange,如下例所示。
假设您有以下 类:
public class Recipe
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
public List<Product> Products { get; set; } = new();
}
public class Product
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public Recipe Recipe { get; set; }
}
您可以如下实例化使用:
public static void Main()
{
var recipe = new Recipe
{
Name = "My Recipe",
Products = new List<Product>
{
new Product { Name = "Product 1" },
new Product { Name = "Product 2" },
new Product { Name = "Product 3" }
}
};
recipe.Products.ForEach(product =>
{
Console.WriteLine(product.Name);
});
}
听起来您正在寻找 many-to-many 关系而不是 one-to-many。
如果您使用的是 Code-First 和 EF6 或 EF Core 5+,那么您可以使用:
public class Recipe
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
public virtual ICollection<Product> Products { get; set; } = new List<Product>();
}
public class Product
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
public virtual ICollection<Recipe> Recipes { get; set; } = new List<Recipe>();
}
要了解幕后发生的事情,EF 应该创建一个名为 ProductRecipe 或 RecipeProduct 的联接 table,其中包含两个 FK。 ProductId 和 RecipeId。这些也将构成本table的复合PK。使用此 table,EF 可以将一种产品关联到多个配方,同时还将一种配方关联到各种产品。在对象模型中,您获得每个配方的产品集合,以及每个产品的配方集合。
对于早期版本的 EF Core,您仅限于必须声明此链接实体,因此您会得到更像的东西:
public class Recipe
{
// ...
public virtual ICollection<ProductRecipe> ProductRecipes { get; set; } = new List<ProductRecipe>();
}
public class Product
{
// ...
public virtual ICollection<ProductRecipe> ProductRecipes { get; set; } = new List<ProductRecipe>();
}
public class ProductRecipe
{
[Key, Column(Order = 0)]
public int ProductId { get; set; }
[Key, Column(Order = 1)]
public int RecipeId { get; set; }
public virtual Product Product { get; set; }
public virtual Recipe Recipe { get; set; }
}
此方法在其他版本的 EF 中仍然是一个选项,并且是必需的如果您希望支持向连接添加任何其他字段table。例如,如果您想要跟踪 CreatedDate/ModifiedDate 等内容以记录产品何时与食谱相关联等。要通过 EF 将该信息公开给应用程序,EF 需要将 ProductRecipe 作为一个实体了解。权衡的是,当您通常关心配方的产品等时,这种方法会“更混乱”。要获取配方的产品列表,您需要:
var products = context.Products
.Where(p => p.ProductRecipes.Any(pr => pr.RecipeId == recipeId)
.ToList();
或
var products = context.Recipies
.Where(r => r.RecipeId == recipeId)
.SelectMany(r => r.ProductRecipies.Select(pr => pr.Product).ToList())
.ToList();
对比第一种方法中的隐含连接 table:
var produts = context.Recipes
.Where(r => r.RecipeId == recipeId)
.SelectMany(r => r.Products)
.ToList();
...这可以说更容易阅读。
更新: 目前我只能将一种产品分配给 Recipe。我想要做的是在配方(控制器创建)中添加对数据库中所有产品的访问权限 - 这里我使用 public int ProductId 但它只允许保存一个产品。我想从此列表中选择一些产品并将外键保存在数据库中。 photo
我也尝试在 ProductId 中添加 public List < int > 但我从 entity framework.
中收到错误如有任何帮助,我将不胜感激。
public class Recipe
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public int ProductId { get; set; }
public List<Product> Products { get; set; }
public Recipe()
{
this.Products = new List<Product>();
}
}
public class Product
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public Recipe? Recipes { get; set; }
}
如果你想创建一个 one-to-many 关系,你几乎是在正确的方向,但你应该删除 public int ProductId { get; set; }
和 re-arrange,如下例所示。
假设您有以下 类:
public class Recipe
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
public List<Product> Products { get; set; } = new();
}
public class Product
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public Recipe Recipe { get; set; }
}
您可以如下实例化使用:
public static void Main()
{
var recipe = new Recipe
{
Name = "My Recipe",
Products = new List<Product>
{
new Product { Name = "Product 1" },
new Product { Name = "Product 2" },
new Product { Name = "Product 3" }
}
};
recipe.Products.ForEach(product =>
{
Console.WriteLine(product.Name);
});
}
听起来您正在寻找 many-to-many 关系而不是 one-to-many。
如果您使用的是 Code-First 和 EF6 或 EF Core 5+,那么您可以使用:
public class Recipe
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
public virtual ICollection<Product> Products { get; set; } = new List<Product>();
}
public class Product
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
public virtual ICollection<Recipe> Recipes { get; set; } = new List<Recipe>();
}
要了解幕后发生的事情,EF 应该创建一个名为 ProductRecipe 或 RecipeProduct 的联接 table,其中包含两个 FK。 ProductId 和 RecipeId。这些也将构成本table的复合PK。使用此 table,EF 可以将一种产品关联到多个配方,同时还将一种配方关联到各种产品。在对象模型中,您获得每个配方的产品集合,以及每个产品的配方集合。
对于早期版本的 EF Core,您仅限于必须声明此链接实体,因此您会得到更像的东西:
public class Recipe
{
// ...
public virtual ICollection<ProductRecipe> ProductRecipes { get; set; } = new List<ProductRecipe>();
}
public class Product
{
// ...
public virtual ICollection<ProductRecipe> ProductRecipes { get; set; } = new List<ProductRecipe>();
}
public class ProductRecipe
{
[Key, Column(Order = 0)]
public int ProductId { get; set; }
[Key, Column(Order = 1)]
public int RecipeId { get; set; }
public virtual Product Product { get; set; }
public virtual Recipe Recipe { get; set; }
}
此方法在其他版本的 EF 中仍然是一个选项,并且是必需的如果您希望支持向连接添加任何其他字段table。例如,如果您想要跟踪 CreatedDate/ModifiedDate 等内容以记录产品何时与食谱相关联等。要通过 EF 将该信息公开给应用程序,EF 需要将 ProductRecipe 作为一个实体了解。权衡的是,当您通常关心配方的产品等时,这种方法会“更混乱”。要获取配方的产品列表,您需要:
var products = context.Products
.Where(p => p.ProductRecipes.Any(pr => pr.RecipeId == recipeId)
.ToList();
或
var products = context.Recipies
.Where(r => r.RecipeId == recipeId)
.SelectMany(r => r.ProductRecipies.Select(pr => pr.Product).ToList())
.ToList();
对比第一种方法中的隐含连接 table:
var produts = context.Recipes
.Where(r => r.RecipeId == recipeId)
.SelectMany(r => r.Products)
.ToList();
...这可以说更容易阅读。