使用 DBSet<>创建循环引用
本文关键字:循环 引用 创建 DBSet 使用 | 更新日期: 2023-09-27 18:36:37
我似乎无法弄清楚如何使用实体框架引用另一个dll(在同一解决方案中)中的类
错误 1 找不到类型或命名空间名称"Animal"(是否缺少 using 指令或程序集引用?
如果我尝试添加引用,我将创建一个循环引用。
public class AnimalDBContext : DbContext
{
public AnimalDBContext()
: base()
{
}
public DbSet<Animal> Animals { get; set; }
}
这是对我来说似乎更正确的版本。但未必呢?
public class AnimalDBContext<TEntity> where TEntity : DbContext
{
public AnimalDBContext()
: base()
{
}
public DbSet<TEntity> Animals { get; set; }
}
这会导致以下编译器错误。
AnimalDBContext < Animal > animal = new AnimalDBContext<Animal>();
Error 3 The type 'AnimalLibrary.Animals.Animal' cannot be used as type
parameter 'TEntity' in the generic type or method
ObjectSaver.AnimalDBContext<TEntity>'. There is no implicit reference conversion from
AnimalLibrary.Animals.Animal' to 'System.Data.Entity.DbContext'.
因此,如果我理解正确,您的"存储库"程序集引用您的"域"程序集,这是有意义的,而您的"域"程序集引用您的"存储库"程序集,而"存储库"程序集则不然。
出于以下几个原因,实体类不应引用用于创建它们的存储库:
- 正如您所发现的那样,它创建了一个循环依赖关系
- 这使得模拟单元测试类变得更加困难
- 您的实体绑定到一种类型的提供程序,因此将来很难更改提供程序
将存储库上的依赖项从域移动到单独的程序集中。
根据您的评论,听起来您至少需要三个组件 -
- A) 数据访问,
- B) 业务逻辑,以及
- C) 域类。
理想情况下,A 和 B 应该引用 C,而不是彼此引用(反之亦然)。 您的域类不需要知道如何持久化自己 - 这是其他人的责任。
您可以从 A 引用 B,但这会阻止您"模拟"存储库来测试业务逻辑。 将数据访问和业务逻辑绑定到主应用程序引用的"服务"层中。 同样,您可以将服务和应用程序层捆绑在一起,但这也会增加耦合并降低可测试性。