![](/img/trans.png)
[英]Code First Entity Framework doesn't create one to many relationship
[英]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 的一些充分理由:
考虑存储库的一些不好(尽管很常见)的原因:
投影到 DTO 或 ViewModel 是使用 EF 构建高效且安全的解决方案的一个重要方面。 目前尚不清楚“ObjectMapper”是什么,无论它是 Automapper Mapper 实例还是其他东西。 我强烈建议通过使用 Linq 的Select
语法从模型中填充所需的 DTO 来开始掌握投影。 使用投影时,正确的第一个关键的区别是,当你的项目的对象图,你不必急于左右装载相关实体的担心。 投影 ( Select
) 中引用的任何相关实体/属性将根据需要自动加载。 稍后,如果您想利用 Automapper 之类的工具来帮助消除Select
语句的混乱,您将需要配置映射配置,然后使用 Automapper 的ProjectTo
方法而不是Map
。 ProjectTo
与 EF 的IQueryable
实现一起使用,将您的映射解析为 SQL,就像Select
一样,其中Map
需要返回所有预先加载的内容以填充相关数据。 ProjectTo
和Select
可以产生更高效的查询,与 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.