C# 在实体框架核心中实现工作单元

C# 在实体框架核心中实现工作单元,c#,entity-framework-core,asp.net-core-webapi,autofac,C#,Entity Framework Core,Asp.net Core Webapi,Autofac,我已经在实体框架核心中以下一种方式实现了工作单元 背景: public class DaleContext : DbContext, IDaleContext { private readonly IConnectionStringProvider _connectionStringProvider; protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {

我已经在实体框架核心中以下一种方式实现了工作单元

背景:

public class DaleContext : DbContext, IDaleContext
{
    private readonly IConnectionStringProvider _connectionStringProvider;

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(_connectionStringProvider.ConnectionString);
        base.OnConfiguring(optionsBuilder);
    }

    public DaleContext(IConnectionStringProvider connectionStringProvider)
    {
        _connectionStringProvider = connectionStringProvider;
    }
    
    public DbSet<ProductProducts { get; set; }

    public override int SaveChanges()
    {
        ChangeTracker.DetectChanges();

        var modifiedEntries = ChangeTracker.Entries()
            .Where(x =x.State == EntityState.Added || x.State == EntityState.Modified).ToList();

        return base.SaveChanges();
    }
}
当然,所有这些都是注入的:

    private readonly ICustomerRepository _customerRepository;
    private readonly IProductRepository _productRepository;
    private readonly ISaleDetailRepository _saleDetailRepository;
    private readonly ISaleRepository _saleRepository;
    private readonly IUnitOfWork _unitOfWork;

    public DaleApplicationService(IProductRepository productRepository, ICustomerRepository customerRepository,
        ISaleRepository saleRepository, ISaleDetailRepository saleDetailRepository, IUnitOfWork unitOfWork)
    {
        _productRepository = productRepository;
        _customerRepository = customerRepository;
        _saleRepository = saleRepository;
        _saleDetailRepository = saleDetailRepository;
        _unitOfWork = unitOfWork;
    }
我错过了什么


注:所有这些都适用于.NET核心Web Api。

正如@zolty13所暗示的那样,
DbContext
DaleContext
)可能不正确。默认情况下,Autofac将实例范围设置为(也称为“瞬态”生存期),这意味着将为依赖它的每个类创建
DaleContext
的新实例。因此,您的
UnitOfWork
接收的
DaleContext
实例与
IProductRepository
不同。因此,
IProductRepository
中的更改不会反映在
UnitOfWork

解决这个问题的一种方法是避免像@Igor suggest这样复杂地包装DbContext。你真的需要这个工作单元吗?相反,使用一个具有
DaleContext
实例的存储库类,并在其中进行所有DB更改并保存它们

或者(如果你真的认为你需要一个
工作单元
),你可以用一个作用域注册你的
DaleContext
。注意:实体框架的DbContext不是线程安全的,所以如果您需要并发工作,这不是一种安全的方法


否则,请继续阅读。

您确定di作用域是好的吗?请尝试只发布相关代码。太多的代码只会模糊你的问题。此外,写“当我试图保存数据时,它不起作用”并不能真正解释你的感受。你犯了什么错误?到底哪里出了问题?如果你能指出代码中的某一行,那就更好了。@zolty13我认为是的。。。但是如何跟踪呢?@Xerilio更新了
“我已经在entity framework core中以下一种方式实现了工作单元:“
← 为什么?类型
DbContext
是UoW模式的实现,类型
DbSet
是存储库模式的实现。为什么要在您自己的相同模式实现中重新包装这些类型?您没有添加任何有价值的东西,只是添加了更多的代码和糟糕的抽象,这导致代码更难阅读、调试和使用。
public class Repository<TEntity: IDisposable, IRepository<TEntity>
where TEntity : class
{
    private readonly UnitOfWork _unitOfWork;

    public Repository(IUnitOfWork unitOfWork)
    {
        _unitOfWork = unitOfWork as UnitOfWork;
    }

    public void Dispose()
    {
        _unitOfWork.DbContext.Dispose();
    } 

    public void Create(TEntity entity)
    {
        _unitOfWork.DbContext.Entry(entity).State = EntityState.Added;
    }
}
public static class Container
{
    public static ContainerBuilder RegisterInfraestructure(this ContainerBuilder containerBuilder)
    {
        containerBuilder.RegisterType<UnitOfWork>().As<IUnitOfWork>();

        return containerBuilder;
    }
}

public static class Container
{
    public static ContainerBuilder RegisterDataResources(this ContainerBuilder containerBuilder)
    {
        var configurationBuilder = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json");

        var configuration = configurationBuilder.Build();

        containerBuilder.Register(x =new ConnectionStringProvider(configuration.GetConnectionString("Fgcm.Dale"))
        ).As<IConnectionStringProvider>();

        containerBuilder.RegisterType<DaleContext>().As<DbContext>().As<IDaleContext>();

        return containerBuilder;
    }
} 

public static class Container
{
    public static ContainerBuilder RegisterRepository(this ContainerBuilder containerBuilder)
    {
        containerBuilder.RegisterType<CustomerRepository>().As<ICustomerRepository>();
        containerBuilder.RegisterType<ProductRepository>().As<IProductRepository>();
        containerBuilder.RegisterType<SaleDetailRepository>().As<ISaleDetailRepository>();
        containerBuilder.RegisterType<SaleRepository>().As<ISaleRepository>();
        
        containerBuilder.RegisterDataResources();
        containerBuilder.RegisterInfraestructure();

        return containerBuilder;
    }
}

public static class Container
{
    public static ContainerBuilder RegisterApplicationServiceResources(this ContainerBuilder
    containerBuilder)
    {
        containerBuilder.RegisterRepository();

        containerBuilder.RegisterType<DaleApplicationService>().As<IDaleApplicationService>();

        return containerBuilder;
    }
}
    public Product Create(Product product)
    {
        try
        {
            _productRepository.Create(product);
            _unitOfWork.Commit();
            return product;
        }
        catch (Exception e)
        {
            Debug.WriteLine(e);
            return null;
        }
    }
    private readonly ICustomerRepository _customerRepository;
    private readonly IProductRepository _productRepository;
    private readonly ISaleDetailRepository _saleDetailRepository;
    private readonly ISaleRepository _saleRepository;
    private readonly IUnitOfWork _unitOfWork;

    public DaleApplicationService(IProductRepository productRepository, ICustomerRepository customerRepository,
        ISaleRepository saleRepository, ISaleDetailRepository saleDetailRepository, IUnitOfWork unitOfWork)
    {
        _productRepository = productRepository;
        _customerRepository = customerRepository;
        _saleRepository = saleRepository;
        _saleDetailRepository = saleDetailRepository;
        _unitOfWork = unitOfWork;
    }