.NET EF Core - 删除存储库和工作统一

发布于 2025-01-11 18:37:51 字数 638 浏览 0 评论 0原文

我使用 .NET 6.0 和 Blazor Server 创建一个应用程序。有时,我的应用程序中出现错误,并显示消息在上一个操作完成之前在此上下文实例上启动了第二个操作。

Blazor 服务器和 EF Core:在上一个操作完成之前,在此上下文实例上启动了第二个操作

我用通常模式存储库。我有每个表和工作单元的存储库来保存和其他。在我之前的问题中,有人向我解释说,我使用 DbContext 不好。因为它是在存储库和工作单元上共享的 dbcontext。我读了很多文章,通常的建议是仅使用自定义 DbContext。我认为这对我来说不是问题。我需要对我的框架进行一些更改,但是 np.但我不明白一件事。我如何为每个数据库集执行自定义通用查询?是否有很多关于将存储库与上下文工厂一起使用但没有工作统一的文章。我真的不喜欢所有操作都是独立的并且多次访问数据库这一事实。

您的建议和经验是什么?你有关于这方面的文章或教程吗?

我真的只是在寻找如何使其成为“最好的”并且对我也可用。 非常感谢 :)

i create an app with .NET 6.0 and Blazor Server. Sometimes i got an error in my application with message A second operation was started on this context instance before a previous operation completed.

Blazor Server and EF Core: A second operation was started on this context instance before a previous operation completed

I use normally pattern repository. I have repository for every table and unitofwork to save and other. In my previous question was explained me, that i use DbContext bad. Because it's shared dbcontext over repository and unit of work. I read many articles and usual recommendations was use only custom DbContext. I think it's not problem for me. I need to some changes in my framework but np. But i don't understand one thing. How i can do my custom generic queries for every dbset? Was there many articles about use repository with context factory and without unity of work. I don't really like the fact that all the operations are separate and access to database many times.

What is your recommendation and your expirience? Do you have any articles or tutorials about that?

I'm really just looking for how to make it the "best" and also usable for me.
Thank you very much :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

痴骨ら 2025-01-18 18:37:51

DbContext 的设计是短暂的。为每个操作创建一个新的上下文实例以解决您的问题。

您的 DbContext 应该是这样的,以便于构建。

public class SomeDbContext : DbContext
{
     private readonly IConfiguration configuration;

     public SomeDbContext(IConfiguration configuration)
     {
         this.configuration = configuration;
         // this.Database.Migrate(); <- optional
     }

    DbSet<SomeValue> SomeValues { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        string connectionString =
            this.configuration.GetConnectionString("DefaultConnection");

        optionsBuilder.UseSqlServer(connectionString);
    }


    public async ValueTask<SomeValue> InsertSomeValueAsync(SomeValue someValue)
    {
        using var someDbContext = new SomeDbContext(this.configuration);

        EntityEntry<SomeValue> entityEntry =
            await someDbContext.SomeValues.AddAsync(entity: someValue);

        await someDbContext.SaveChangesAsync();

        return entityEntry.Entity;
    }
}

InsertSomeValueAsync 方法可以轻松地变得通用。

    public async ValueTask<T> InsertSomeValueAsync<T>(T someValue)
        where T : class
    {
        using var someDbContext = new SomeDbContext(this.configuration);

        EntityEntry<T> entityEntry =
            await someDbContext.AddAsync(someValue);

        await someDbContext.SaveChangesAsync();

        return entityEntry.Entity;
    }

DbContext's are designed to be short-lived. Create a new instance of your context for each operation to resolve your issue.

Your DbContext would be something like this to make it easy to construct.

public class SomeDbContext : DbContext
{
     private readonly IConfiguration configuration;

     public SomeDbContext(IConfiguration configuration)
     {
         this.configuration = configuration;
         // this.Database.Migrate(); <- optional
     }

    DbSet<SomeValue> SomeValues { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        string connectionString =
            this.configuration.GetConnectionString("DefaultConnection");

        optionsBuilder.UseSqlServer(connectionString);
    }


    public async ValueTask<SomeValue> InsertSomeValueAsync(SomeValue someValue)
    {
        using var someDbContext = new SomeDbContext(this.configuration);

        EntityEntry<SomeValue> entityEntry =
            await someDbContext.SomeValues.AddAsync(entity: someValue);

        await someDbContext.SaveChangesAsync();

        return entityEntry.Entity;
    }
}

The InsertSomeValueAsync method could easily be made generic.

    public async ValueTask<T> InsertSomeValueAsync<T>(T someValue)
        where T : class
    {
        using var someDbContext = new SomeDbContext(this.configuration);

        EntityEntry<T> entityEntry =
            await someDbContext.AddAsync(someValue);

        await someDbContext.SaveChangesAsync();

        return entityEntry.Entity;
    }
Oo萌小芽oO 2025-01-18 18:37:51

一种选择是使用 DBContextFactory 来管理上下文。

这是我的一个应用程序中的一些示例代码。

Program

var dbConnectionString = builder.Configuration.GetValue<string>("MyConfiguration:ConnectionString");
builder.Services.AddDbContextFactory<MySqlServerDbContext>(options => options.UseSqlServer(dbConnectionString), ServiceLifetime.Singleton);

并在(通用)数据代理中使用它:

public class ServerDataBroker
    : IDataBroker
{
    private IDbContextFactory<MySqlServerDbContext> _dbContextFactory;

    public ServerDataBroker(IDbContextFactory<MySqlServerDbContext> factory)
        => _dbContextFactory = factory;

//.....
    public async ValueTask<int> GetRecordCountAsync<TRecord>() where TRecord : class, new()
    {
        using var context = _dbContextFactory.CreateDbContext();
        var dbSet = context.Set<TRecord>();
        return dbSet is not null
         ? await dbSet.CountAsync()
         : 0;
    }
//.....

这里有一篇关于它的 MS-Docs 文章 - https://learn.microsoft.com/en-us/ef/core/dbcontext-configuration/

在测试中,我使用 EF InMemory - 您可以将 Factory 与它一起使用。询问您是否想要指向某些代码。

One option is to use a DBContextFactory to manage the contexts.

Here's some example code from one of my applications.

Program

var dbConnectionString = builder.Configuration.GetValue<string>("MyConfiguration:ConnectionString");
builder.Services.AddDbContextFactory<MySqlServerDbContext>(options => options.UseSqlServer(dbConnectionString), ServiceLifetime.Singleton);

And using it in a (generic) data broker:

public class ServerDataBroker
    : IDataBroker
{
    private IDbContextFactory<MySqlServerDbContext> _dbContextFactory;

    public ServerDataBroker(IDbContextFactory<MySqlServerDbContext> factory)
        => _dbContextFactory = factory;

//.....
    public async ValueTask<int> GetRecordCountAsync<TRecord>() where TRecord : class, new()
    {
        using var context = _dbContextFactory.CreateDbContext();
        var dbSet = context.Set<TRecord>();
        return dbSet is not null
         ? await dbSet.CountAsync()
         : 0;
    }
//.....

There's an MS-Docs article about it here - https://learn.microsoft.com/en-us/ef/core/dbcontext-configuration/.

On testing, I use EF InMemory - you can use the Factory with it. Ask if you want to be pointed to some code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文