我坚持如何设计我的配方模型,以便可以与EF Core一起使用。我发现它很复杂,因为这些成分可以只是原料,也可以是其他配方。 我有以下型号:
public interface IIngredient
{
int Id { get; }
string Name { get; }
decimal KiloPrice { get; }
}
public class RawMaterial : IIngredient
{
public int Id { get; set; }
public string Name { get; set; }
public decimal KiloPrice { get; set; }
}
public class Recipe : IIngredient
{
public int Id { get; set; }
public string Name { get; set; }
public decimal KiloPrice =>
RecipeLines.Sum(x => x.Ingredient.KiloPrice * x.Quantity) /
RecipeLines.Sum(x => x.Quantity);
public List<RecipeLine> RecipeLines { get; set; }
}
public class RecipeLine
{
public int Id { get; set; }
public IIngredient Ingredient { get; set; }
public decimal Quantity { get; set; }
}
是否甚至可以让EF Core映射IIngredient?因为这意味着当原料是RawMaterial时,可以轻松获取KiloPrice,但是当原料是Recipe时,则需要加载RecipeLines来计算KiloPrice。
答案 0 :(得分:0)
很遗憾,EfCore无法映射接口。解决方法是使用Abstract类。我知道这与设计背道而驰,但这是您所能做到的。
public interface IIngredient
{
int Id { get; }
string Name { get; }
decimal KiloPrice { get; }
}
public abstract class BaseIngredient:IIngredient
{
int Id { get; }
string Name { get; }
decimal KiloPrice { get; }
}
public class RawMaterial : BaseIngredient
{
public int Id { get; set; }
public string Name { get; set; }
public decimal KiloPrice { get; set; }
}
public class Recipe : BaseIngredient
{
public int Id { get; set; }
public string Name { get; set; }
public decimal KiloPrice =>
RecipeLines.Sum(x => x.Ingredient.KiloPrice * x.Quantity) /
RecipeLines.Sum(x => x.Quantity);
public List<RecipeLine> RecipeLines { get; set; }
}
然后,如果您确实要使用接口,则可以使用基类类型的后备字段和接口类型的公共属性。
public class RecipeLine
{
public int Id { get; set; }
private readonly BaseIngredient _ingredient;
public IIngredient Ingredient=>_ingredient;
public decimal Quantity { get; set; }
}
在您的ModelBuilder中,您需要将PropertyAccessMode指定为字段。
答案 1 :(得分:0)
我不一定需要使用接口。我正在尝试使用您建议的基类。
public abstract class BaseIngredient
{
public int Id { get; set; }
public string Name { get; set; }
public decimal KiloPrice { get; }
}
public class RawMaterial : BaseIngredient
{
public decimal KiloPrice { get; set; }
}
public class Recipe : BaseIngredient
{
public new decimal KiloPrice =>
RecipeLines.Sum(x => x.Ingredient.KiloPrice * x.Quantity) /
RecipeLines.Sum(x => x.Quantity);
public virtual ICollection<RecipeLine> RecipeLines { get; set; }
}
public class RecipeLine
{
public int Id { get; set; }
public int RecipeId { get; set; }
public Recipe Recipe { get; set; }
public int BaseIngredientId { get; set; }
public BaseIngredient Ingredient { get; set; }
public decimal Quantity { get; set; }
}
public class SqliteDbContext :DbContext
{
public DbSet<RawMaterial> RawMaterials { get; set; }
public DbSet<Recipe> Recipes { get; set; }
public DbSet<RecipeLine> RecipeLines { get; set; }
public DbSet<BaseIngredient> BaseIngredients { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<RawMaterial>().ToTable("RawMaterial");
modelBuilder.Entity<Recipe>().ToTable("Recipe");
modelBuilder.Entity<BaseIngredient>().ToTable("BaseIngredient");
modelBuilder.Entity<RawMaterial>()
.HasBaseType<BaseIngredient>();
modelBuilder.Entity<Recipe>()
.HasBaseType<BaseIngredient>();
modelBuilder.Entity<BaseIngredient>()
.HasDiscriminator<string>("Discriminator")
.HasValue<BaseIngredient>("BaseIngredient")
.HasValue<RawMaterial>("RawMaterial")
.HasValue<Recipe>("Recipe");
modelBuilder.Entity<RecipeLine>()
.HasOne(x => x.Ingredient);
modelBuilder.Entity<RecipeLine>()
.HasOne(x => x.Recipe)
.WithMany(x => x.RecipeLines)
.HasForeignKey(x => x.RecipeId);
}
}
当我使用RecipeLines保存配方时,由于复制了Ingrediënt而收到了ID约束错误。当我第一次保存配方,然后向其添加RecipeLines时,这种关系确实起作用。
但是我现在真正的问题是,KiloPrice始终为0。