问题描述
我正在建立一个编辑现有配方的项目
请注意--每个食谱可以包含多个成分组 (这是我构建此项目的重点)
- 食谱表(食谱ID,名称等)
- 每个配方的成分组链接表 ChartsForOneRecipe (组ID,组名称:(以调味料为基础))
- 有成分表(ID和名称)
- 具有所有成分组 ingredientsInChart 的成分列表的表(每种成分的ID,其所属的成分组的ID,成分ID,数量等)
有人知道我如何找出与一个成分组相关的成分名称吗? 在C#MVC中,当然不在sql
中我的问题是:
如何在一个功能中执行此操作? 如何正确编写它会起作用。 如果有可能不复制或创建新表。
注意 我的桌子上还没有任何FK。 最后,我需要从数据库中获取每个配方的成分组。 并且所有成分组都在一个表中,并且只有成分的ID,组的ID,而没有名称。
我已经开始编写此功能:
在“配方”控制器中:
mydata db = new data()
private List<ChartsForOneRecipe> lchart;
-
[HttpGet] public IHttpActionResult GetTheNamesOfChartsByRecipeId(int RecipeId) { lchart = db.ChartsForOneRecipe.Where(ch => ch.recipeId == RecipeId).ToList(); return base.Ok(lchart); }
-
[HttpGet]//return all ingredients in a chart by getting chartid public IHttpActionResult GetAlltheIngredientsInChart(int ChartId) { var q = from ing in db.Ingredients from ingch in db.IngredientsInChart where (ing.ingredientID == ingch.ingredientsInChartId && ingch.chartId == ChartId) select new { ing.ingredientID,ing.name }; return Ok(q);
}
解决方法
考虑到您正在使用EF6 Code First,并用各自的Data Annotation定义了模型来设置密钥,如下所示:
public class Ingredients
{
[Key]
public int IngredientId { get; set; }
public string Name { get; set; }
//Begin Other irrelevant attributes
//...
//End irrelevant attributes
//Navigation property - THIS IS IMPORTANT
[ForeignKey("IngredientsInChartId")]
public ICollection<IngredientsInChart> IngredientsInChart { get; set; }
}
public class IngredientsInChart
{
[Key]
public int ChartId { get; set; }
public string Name { get; set; }
//Begin Other irrelevant attributes
//...
//End irrelevant attributes
//Optional,on using FLUENT-API for seeding data (Migration)
public int IngredientsInChartId { get; set; }
//Navigation property - THIS IS IMPORTANT
[ForeignKey("IngredientsInChartId")]
public Ingredients Ingredient { get; set; }
}
或者您可能更愿意使用FluentAPI来设置您的上下文:
public class MyData : DbContext
{
public virtual DbSet<ChartsForOneRecipe> ChartsForOneRecipe { get; set; }
public virtual DbSet<Recipe> Recipe { get; set; }
//Other irrelevant DBSet properties
public MyData(DbContextOptions<PharmaDbContext> options) : base(options) { }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// Primary keys
modelBuilder.Entity<Ingredients>()
.Property(c => c.IngredientId)
.UseIdentityAlwaysColumn();
modelBuilder.Entity<IngredientsInChart>()
.Property(c => c.ChartId)
.UseIdentityAlwaysColumn();
//Foreign keys
modelBuilder.Entity<Ingredients>()
.HasMany(c => c.IngredientsInChart)
.WithOne(k => k.Ingredient)
.HasForeignKey(fk => fk.IngredientsInChartId);
modelBuilder.Entity<IngredientsInChart>()
.HasOne(k => k.Ingredient)
.WithMany(c => c.IngredientsInChart)
.HasForeignKey(fk => fk.IngredientsInChartId);
}
}
最后,我们可以按以下方式加载数据:
急切加载
使用紧急加载方法,必须先加载所有 Ingredient ,然后再加载相关的 IngredientsInChart :
[HttpGet]//return all ingredients in a chart by getting chartid
public IHttpActionResult GetAlltheIngredientsInChart(int ChartId)
{
var ingredients = db.Ingredients.ToList();
var q = db.IngredientsInChart.Where(ingch => ingch.Id == ChartId)
.Include(ingch => ingch.Ingredient)
.Select(ingch => new { ingch.IngredientsInChartId,ingch.Ingredient.Name })
.ToList();
return Ok(q);
}
延迟加载
您不需要加载成分(删除var ingredients = db.Ingredients.ToList();
和Include(ingch => ingch.Ingredient)
)。但是,您可能需要按照以下步骤安装EF Proxy Nuget Package并在Startup项目中进行设置:
public void ConfigureServices(IServiceCollection services)
{
#region Database configuration
// Database configuration
services.AddDbContext<MyData>(options =>
options.UseLazyLoadingProxies()
.UseSqlServer(Configuration.GetConnectionString("MyConnectionString")));
#endregion Database configuration
}
为进一步阅读,我强烈建议阅读:
,前提是您具有在以下查询中可以在IngredientsInChart中设置的导航属性Ingredients
var q = db.IngredientsInChart.Where(inc => inc.chartId == ChartId)
.Include(inc => inc.Ingredient)
.Select(inc => new {
inc.ingredientsInChartId,inc.Ingredient.name
}).ToList();