c# – Entity Framework 6,急切加载嵌套关系返回空集合
我有一个看起来像这样的域模型(剥离了一些不重要的属性)
public class User { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public virtual int UserId { get; set; } private ICollection<Recipe> _recipes; public virtual ICollection<Recipe> Recipes { get { return _recipes ?? new List<Recipe>(); } set { _recipes = value; } } } public class Recipe { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int RecipeId { get; set; } private ICollection<Ingredient> _ingredients; public virtual ICollection<Ingredient> Ingredients { get { return _ingredients ?? new List<Ingredient>(); } set { _ingredients = value; } } public User User { get; set; } } public class Ingredient { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int IngredientId { get; set; } public Recipe Recipe { get; set; } } 简而言之,用户与Recipe有一对多的关系,而Recipe与Ingredient之间存在一对多的关系.我正在使用代码第一种方法,在受保护的覆盖中使用此映射void OnModelCreating(DbModelBuilder modelBuilder): modelBuilder.Entity<User>() .HasMany(u => u.Recipes) .WithRequired(u => u.User) .WillCascadeOnDelete(true); modelBuilder.Entity<Recipe>() .HasMany(u => u.Ingredients) .WithRequired(u => u.Recipe) .WillCascadeOnDelete(true); 我正在使用存储库,它具有此代码将数据存储到MySQL数据库中: public void Add(User entity) { using (var context = new UserContext()) { context.Users.Add(entity); context.SaveChanges(); } } 和取: public User GetById(int id) { using (var context = new UserContext()) { var user = context.Users .Include(u => u.Recipes) .Include(u => u.Recipes.Select(x => x.Ingredients)) .FirstOrDefault(u => u.UserId == id); return user; } } 我有集成测试,它创建一个User对象,List< Recipe>具有两个配方,其中每个配方具有List< Ingredient>有2件物品.每种食谱都有所不同,总共有4种成分.当我将它添加到存储库时,我可以在数据库中看到它具有正确的PK和FK. 但是,从数据库中检索时,返回的User对象具有配方,但这些配方都没有配方.由于我设置我的getter的方式,当我尝试访问它们时,我收到一个空集合. 例如这样做: /* create recipes collection and seed it */ User user = new User {Recipes = recipes /* plus some omitted properites*/}; _repository.Add(user); var returnedUser = _repository.GetById(user.UserId); var userIngredients = user.Recipes.First(u => u.RecipeName == "Test").Ingredients.ToList(); var returnedIngredients = returnedUser.Recipes.First(u => u.RecipeName == "Test").Ingredients.ToList(); returnedIngredients为空,而userIngredients有两个元素.然后这会失败断言并导致集成测试失败. 有人能告诉我如何在嵌套的一对多上正确地进行加载吗? 解决方法
这个:
get { return _recipes ?? new List<Recipe>(); } 应该读: get { return _recipes ?? (_recipes = new List<Recipe>()); } 成分相同. 否则,每次都会返回一个新的空列表(因为它没有存储在任何地方).这仅在整个列表设置在某一点(从数据库读取并覆盖)时才有效,但如果您是按代码创建实体则不会,因为它们将被添加到未存储在支持字段中的列表中. 你看到Recipes已满,因为你在这里设置它:User user = new User {Recipes = recipes / *加上一些省略的属性* /};所以它存储在支持字段中. 但是当你添加它们时,成分不是: var recipe = new Recipe(); recipe.Ingredients.Add(myIngredient); // <-- this will be stored in a // new List<Ingredient>,// but not on the // _ingredients backing field // since the get accesor doesn't // set it recipe.Ingredients.Add(myIngredient); // <-- this will be stored in a // new List<Ingredient>,not in // the expected created one 至于急切的加载,你不需要这个: var user = context.Users .Include(u => u.Recipes) .Include(u => u.Recipes.Select(x => x.Ingredients)) .FirstOrDefault(u => u.UserId == id); 只需: var user = context.Users .Include(u => u.Recipes.Select(x => x.Ingredients)) .FirstOrDefault(u => u.UserId == id); 它会加载两个级别 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |