我具有以下应用程序数据库上下文:
public class ApplicationContext : DbContext
{
private readonly string _connectionString;
public ApplicationContext(IConfiguration configuration)
{
_connectionString = configuration.GetConnectionString("Recipes");
}
public DbSet<User> Users { get; set; }
public DbSet<Recipe> Recipes { get; set; }
public DbSet<Ingredient> Ingridients { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseNpgsql(_connectionString);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Ingredient>()
.HasOne(x => x.Recipe)
.WithMany(y => y.Ingredients);
}
}
我的商业模式很简单:一种食谱有很多成分,而一种成分只有一张收据。
食谱:
public class Recipe
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public List<Ingredient> Ingredients { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
public Recipe()
{
CreatedAt = DateTime.UtcNow;
UpdatedAt = DateTime.UtcNow;
}
}
成分
public class Ingredient
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public int ClientId { get; set; }
public string Name { get; set; }
public decimal Count { get; set; }
public string Measure { get; set; }
public int Number { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
public Recipe Recipe { get; set; }
public Ingredient()
{
CreatedAt = DateTime.UtcNow;
UpdatedAt = DateTime.UtcNow;
}
}
在这里,我正在尝试从食谱中收集食材:
List<Recipe> recipes;
recipes = _applicationContext.Recipes.Where(r => r.Category.ClientId == id).ToList();
但是成分始终为空。我不明白为什么。结果如下:
怎么了?
答案 0 :(得分:2)
您需要在查询中包括子属性,否则将从它们返回null。这样做是为了保持Entity Framework的快速性能。如果自动包含所有子属性,则在EF生成的sql查询中可能会生成许多不必要的联接,这可能会对性能造成很大的影响(如果是这种情况,我们可能会使用.Exclude
扩展方法! )
即:
List<Recipe> recipes = _applicationContext.Recipes.Include(x => x.Ingredients).Where(r => r.Category.ClientId == id).ToList();
答案 1 :(得分:1)
除了@GregH所说的以外,您可以将Ingredients
标记为virtual
,以便可以将它们延迟加载。
public class Recipe
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public virtual List<Ingredient> Ingredients { get; set; } // marked as virtual
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
public Recipe()
{
CreatedAt = DateTime.UtcNow;
UpdatedAt = DateTime.UtcNow;
}
}
现在,您可以按照接受的答案中的说明急于加载它们,也可以像以前尝试过的那样延迟加载它们。
答案 2 :(得分:1)
如果要将导航属性延迟加载,我认为您需要将它们设置为虚拟。
public virtual ICollection<Ingredient> Ingredients { get; set; }
或者您可以将它们包括在查询中,以便与收件人同时获取它们。
recipesWithIngredients = _applicationContext.Recipes
.Include(r => r.Ingredients)
.Where(r => r.Category.ClientId == id)
.ToList();