Entity framework efcore2dbcontext的抽象

Entity framework efcore2dbcontext的抽象,entity-framework,.net-core,entity-framework-core,asp.net-core-2.0,Entity Framework,.net Core,Entity Framework Core,Asp.net Core 2.0,我正试图在我的数据库上下文层(EntityFramework 2.0)上进行抽象。 Car.DataContext ------------------- public abstract class BaseCarContext : DbContext { protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Enti

我正试图在我的数据库上下文层(EntityFramework 2.0)上进行抽象。

Car.DataContext
 ------------------- 
 public abstract class BaseCarContext : DbContext
    {
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Car>(e =>
            {
                e.ToTable("Car");             
            });
            modelBuilder.Entity<Car>(e => { e.ToTable("Cars"); });
        }
    }

     public class CarContext : BaseCarContext
    {
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (optionsBuilder.IsConfigured)
                return;

            optionsBuilder.UseSqlServer(@"Server = xxxx; Database = xxxx; Trusted_Connection = True;");
        }

        public DbSet<Car> Cars { get; set; }        
    }

 Car.Logic
 ----------------
 public interface ICarService
 {
    GetCarResponse RetrieveCar(int id);
    void Save(int id);
    ...
 }

 public class CarService : ICarService
 {
    private readonly ICarService service;   
    // dbContext interface

    public CarService(ICarService service){
        this.service = service; 
        // injecting db context interface
    }

    public void Save(int id){
        ... saving using injected db context
        // injected db context.Insert(new Car{ Name = "Honda" });
    }
    ...
 }
Car.DataContext
------------------- 
公共抽象类BaseCarContext:DbContext
{
模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder)
{
实体(e=>
{
e、 可折叠(“汽车”);
});
实体(e=>{e.ToTable(“Cars”);});
}
}
公共类CarContext:BaseCarContext
{
配置时受保护的覆盖无效(DBContextOptions Builder Options Builder)
{
如果(optionsBuilder.IsConfigured)
返回;
optionsBuilder.UseSqlServer(@“服务器=xxxx;数据库=xxxx;可信连接=True;”);
}
公共数据库集车辆{get;set;}
}
汽车。逻辑
----------------
公共接口ICarService
{
GetCarResponse检索卡(int id);
无效保存(int-id);
...
}
公共类CarService:ICarService
{
专用只读ICarService服务;
//dbContext接口
公共汽车服务(ICarService服务){
服务=服务;
//注入数据库上下文接口
}
公共无效保存(int-id){
…使用注入的db上下文保存
//Insert(新车{Name=“Honda”});
}
...
}
如何提取ef core 2
CarContext
以使用
dbContext
save

我试图制作一个接口
IDbContext
,该接口由
CarContext
但这样我就不能使用
dbContext.Cars.Insert
,因为我没有实现dbContext-Cars集合,所以我无法访问ef核心方法和属性

我当然可以使用具体的实现,但我正在尝试做一个抽象,这样我就可以使用单元测试


您将如何做到这一点?

首先,您不需要对单元测试进行抽象。EF核心是100%测试友好型。其次,在我看来,对于EF(或任何ORM)来说,唯一真正可以接受的抽象是微服务或CQRS/事件源模式。它们实际上增加了价值,因为它们要么完全抽象依赖关系,要么解决实际的业务线问题。然而,这些模式也需要大量的努力才能正确实现,因此,它们通常是为大型、复杂的应用程序保留的


无论长短,只要直接使用EF,除非你有真正好的理由不这样做。测试不是一个很好的理由。

首先,单元测试不需要抽象。EF核心是100%测试友好型。其次,在我看来,对于EF(或任何ORM)来说,唯一真正可以接受的抽象是微服务或CQRS/事件源模式。它们实际上增加了价值,因为它们要么完全抽象依赖关系,要么解决实际的业务线问题。然而,这些模式也需要大量的努力才能正确实现,因此,它们通常是为大型、复杂的应用程序保留的


无论长短,只要直接使用EF,除非你有真正好的理由不这样做。测试不是一个很好的理由。

“EF Core是100%测试友好型的。”我不能同意这一点。我不能嘲笑SaveChange返回的内容。此外,如果使用ExecuteSqlCommand,测试将崩溃,因为UseInMemoryDatabase不支持它:“只有当上下文使用关系数据库提供程序时,才能使用特定于关系的方法”。
SaveChanges
返回受影响的记录计数。你怎么不能模拟返回一个int?其次,使用内存中的数据库不会是模仿。如果您实际上模拟了上下文,则可以存根
ExecuteSqlCommand
执行任何您想要的操作。你不了解如何正确测试并不是EF-Core的缺陷。“EF-Core是100%测试友好型的。”我不能同意这一点。我不能嘲笑SaveChange返回的内容。此外,如果使用ExecuteSqlCommand,测试将崩溃,因为UseInMemoryDatabase不支持它:“只有当上下文使用关系数据库提供程序时,才能使用特定于关系的方法”。
SaveChanges
返回受影响的记录计数。你怎么不能模拟返回一个int?其次,使用内存中的数据库不会是模仿。如果您实际上模拟了上下文,则可以存根
ExecuteSqlCommand
执行任何您想要的操作。您不了解如何正确测试并不是EF Core的缺陷。