繁体   English   中英

一对多关系不检索实体框架中的数据

[英]One to many relationship doesn`t retrieve data in entity framework

我正在学习 C# & .NET 和 EF(使用aspnetboilerplate ),我想出了创建一些虚拟项目的想法,以便我可以练习。 但是最后 4 小时我坚持这个错误,希望这里有人可以帮助我。

我创建的(至少我认为我正确地创建了它)是 2 个名为“成分”和“大师”的类

我想用它对“大师”类的成分进行分类。

例如成分像

  • 鸡胸肉
  • 鸡腿

它们都属于 Meat(女巫在“Master”数据库中输入),这是我的代码

成分.cs

   public class Ingrident : Entity
{

    public string Name { get; set; }
    public Master Master { get; set; }
    public int MasterId { get; set; }

}

硕士.cs

public class Master : Entity

    {
        public string Name { get; set; }
        public List<Ingrident> Ingridents { get; set; } = new();
    
    }

IngridientAppService.cs

public List<IngridientDto> GetIngWithParent()
    {
        var result = _ingRepository.GetAllIncluding(x => x.Master);
         //Also I try this but doesn`t work 
        // var result = _ingRepository.GetAll().Where(x => x.MasterId == x.Master.Id);
        return ObjectMapper.Map<List<IngridientDto>>(result);
    }

配料表

  [AutoMap(typeof(IndexIngrident.Entities.Ingrident))]

public class IngridientDto : EntityDto
{
    public string Name { get; set; }
    public List<MasterDto> Master { get; set; }

    public int MasterId { get; set; }
 }

MasterDto.cs

    [AutoMap(typeof(IndexIngrident.Entities.Master))]

    public class MasterDto : EntityDto
    {
     public string Name { get; set; }
    }

当我创建(最后一次练习)M -> M 关系时,这种方法与 .getAllIn包括工作,但现在当我有一个 -> 许多时,它就行不通了。

希望有人能够帮助我或至少给我一些好的提示。

祝你今天过得愉快 !

直接说明您可能引用的示例(关于存储库等)过于复杂,并且在大多数情况下,不是您想要实现的。

我看到的第一个问题是,虽然您的实体设置为从主到成分的一对多关系,但您的 DTO 是从成分到主设置的,这肯定不会正确映射。

从最简单的事情开始。 摆脱存储库并摆脱 DTO。 我不确定基类“Entity”的作用,但我猜它公开了一个名为“Id”的通用键属性。 对于初学者,我可能也会放弃。 当涉及到主键时,通常有两种命名方法,每个表都使用一个名为“Id”的 PK,或者每个表使用一个表名后缀为“Id”的 PK。 即“Id”与“IngredientId”。 我个人认为第二个选项在配对 FK 和 PK 时非常清楚,因为它们具有相同的名称。

当谈到通过导航属性表示关系时,一个重要的细节是确保导航属性链接到它们各自的 FK 属性(如果存在),或者更好的是,为 FK 使用阴影属性。

例如,对于您的 Ingredient 表,摆脱 Entity 基类:

[Table("Ingredients")]
public class Ingredient : Entity
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int IngredientId { get; set; }
    public string Name { get; set; }
    public int MasterId { get; set; }
    [ForeignKey("MasterId")]
    public virtual Master Master { get; set; }
}

此示例使用 EF 属性来帮助告诉 EF 如何将实体属性解析为相应的表和列,以及 Ingredient 和 Master 之间的关系。 EF 可以通过约定来解决大部分问题,但最好理解并明确应用它,因为最终您会遇到约定无法按预期工作的情况。

识别(主)键并指出它是一个身份列也告诉 EF 期望数据库将自动填充 PK。 (强烈推荐)

在 Master 端,我们做类似的事情:

[Table("Masters")]
public class Master : Entity
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int MasterId { get; set; }
    public string Name { get; set; }
    [InverseProperty("Master")]
    public virtual ICollection<Ingredient> Ingredients { get; set; } = new List<Ingredient>();
}

我们再次表示主键,对于我们的成分集合,我们告诉 EF 在另一侧(成分)应该使用什么属性来关联到使用InverseProperty属性的 Master 的成分列表。

属性只是设置关系等的一个选项。其他选项是使用实现IEntityConfiguration<TEntity> (EF Core) 的配置类,或将它们配置为OnModelCreating事件的一部分。 最后一个选项我只推荐用于非常小的项目,因为它可以很快开始成为一种上帝的方法。 您可以将其拆分为对各种私有方法的调用,但您也可以只使用IEntityConfiguration类。

现在,当您使用 Master 或 Master 获取其成分时:

using (var context = new AppDbContext())
{
    var ingredients = context.Ingredients
        .Include(x => x.Master)
        .Where(x => x.Master.Name.Contains("chicken"))
        .ToList();
    // or

    var masters = context.Master
        .Include(x => x.Ingredients)
        .Where(x => x.Name.Contains("chicken"))
        .ToList();

   // ...
}

存储库模式是一个更高级的概念,有几个很好的理由来实现,但在大多数情况下,它们不是必需的,并且是 EF 实现中的反模式。 我认为通用存储库始终是 EF 实现的反模式。 Repository<Ingredient>使用存储库,尤其是 EF 的通用存储库的主要原因是您会自动增加实现的复杂性和/或削弱 EF 可以为您的解决方案带来的功能。 正如您在使用示例时看到的那样,简单地将急切加载传递到存储库意味着编写复杂的Expression<Func<TEntity>>参数,而这仅涵盖了急切加载。 如果没有 EF 开箱即用的这些功能,支持投影、分页、排序等会增加更多样板复杂性或限制您的解决方案和性能。

考虑研究存储库实现 /w EF 的一些充分理由:

  • 促进单元测试。 (存储库比 DbContexts/DbSets 更容易模拟)
  • 集中低级数据规则,例如租赁、软删除和授权。

考虑存储库的一些不好(尽管很常见)的原因:

  • 从对 EF 的依赖关系的引用或知识中提取代码。
  • 抽象代码,以便可以替换 EF。

投影到 DTO 或 ViewModel 是使用 EF 构建高效且安全的解决方案的一个重要方面。 目前尚不清楚“ObjectMapper”是什么,无论它是 Automapper Mapper 实例还是其他东西。 我强烈建议通过使用 Linq 的Select语法从模型中填充所需的 DTO 来开始掌握投影。 使用投影时,正确的第一个关键的区别是,当你的项目的对象图,你不必急于左右装载相关实体的担心。 投影 ( Select ) 中引用的任何相关实体/属性将根据需要自动加载。 稍后,如果您想利用 Automapper 之类的工具来帮助消除Select语句的混乱,您将需要配置映射配置,然后使用 Automapper 的ProjectTo方法而不是Map ProjectTo与 EF 的IQueryable实现一起使用,将您的映射解析为 SQL,就像Select一样,其中Map需要返回所有预先加载的内容以填充相关数据。 ProjectToSelect可以产生更高效的查询,与 Eager Loading 整个对象图相比,可以更好地利用索引。 (数据库和服务器/应用程序之间的线路上的数据较少) Map仍然非常有用,例如您希望将值从 DTO 复制回已加载实体的场景。

像这样做

public class Ingrident:Entity
{

    public string Name { get; set; }
    [ForeignKey(nameof(MasterId))]
    public Master Master { get; set; }
    public int MasterId { get; set; }

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM