具有多个集合和多个数据库的 ASP.NET Core Web API 和 MongoDB

发布于 2025-01-08 23:53:08 字数 2735 浏览 4 评论 0原文

有了这个问题 ASP.NET Core Web API 和 MongoDB多个集合答案我可以看到mongodb的WITH单个数据库和多个集合的单例和延迟初始化的完美使用。

Startup.cs

public void ConfigureServices(IServiceCollection services)
    {
        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new OpenApiInfo { Title = "Asset Model API", Version = "v1" });
        });

        ConfigureMongoDb(services);

        services.AddControllers()
            .AddJsonOptions(options => options.JsonSerializerOptions.PropertyNamingPolicy = null);
    }

    private void ConfigureMongoDb(IServiceCollection services)
    {
        var settings = GetMongoDbSettings();
        services.AddSingleton(_ => CreateMongoDatabase(settings));

        AddMongoDbService<AuthorService, Author>(settings.AuthorsCollectionName);
        AddMongoDbService<BookService, Book>(settings.BooksCollectionName);

        void AddMongoDbService<TService, TModel>(string collectionName)
        {
            services.AddSingleton(sp => sp.GetRequiredService<IMongoDatabase>().GetCollection<TModel>(collectionName));
            services.AddSingleton(typeof(TService));
        }
    }

    private DatabaseSettings GetMongoDbSettings() =>
        Configuration.GetSection(nameof(DatabaseSettings)).Get<DatabaseSettings>();

    private static IMongoDatabase CreateMongoDatabase(DatabaseSettings settings)
    {
        var client = new MongoClient(settings.ConnectionString);
        return client.GetDatabase(settings.DatabaseName);
    }

BookService.cs

public class BookService
{
    private readonly IMongoCollection<Book> _books;

    public BookService(IMongoCollection<Book> books)
    {
        _books = books;
    }

    public List<Book> Get() => _books.Find(book => true).ToList();
}

BooksController.cs

public class BooksController : ControllerBase
{
    private readonly BookService _bookService;

    public BooksController(BookService bookService)
    {
        _bookService = bookService;
    }

    [HttpGet]
    public ActionResult<List<Book>> Get() => _bookService.Get();
}

我的用例:我有多个数据库和我的 API 端点将接受数据库名称作为参数之一

  [HttpGet]
    public ActionResult<List<Book>> Get(string dbName) => _bookService.Get(dbName);

现在的问题是我的service类和启动类的ConfigureMongoDb方法需要进行哪些更改,以便我可以仍然获得延迟初始化和单例支持吗?

With this question ASP.NET Core Web API and MongoDB with multiple Collections answers I can see the perfect use of singleton and lazy initialization for mongodb's WITH single database and multiple collection.

Startup.cs

public void ConfigureServices(IServiceCollection services)
    {
        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new OpenApiInfo { Title = "Asset Model API", Version = "v1" });
        });

        ConfigureMongoDb(services);

        services.AddControllers()
            .AddJsonOptions(options => options.JsonSerializerOptions.PropertyNamingPolicy = null);
    }

    private void ConfigureMongoDb(IServiceCollection services)
    {
        var settings = GetMongoDbSettings();
        services.AddSingleton(_ => CreateMongoDatabase(settings));

        AddMongoDbService<AuthorService, Author>(settings.AuthorsCollectionName);
        AddMongoDbService<BookService, Book>(settings.BooksCollectionName);

        void AddMongoDbService<TService, TModel>(string collectionName)
        {
            services.AddSingleton(sp => sp.GetRequiredService<IMongoDatabase>().GetCollection<TModel>(collectionName));
            services.AddSingleton(typeof(TService));
        }
    }

    private DatabaseSettings GetMongoDbSettings() =>
        Configuration.GetSection(nameof(DatabaseSettings)).Get<DatabaseSettings>();

    private static IMongoDatabase CreateMongoDatabase(DatabaseSettings settings)
    {
        var client = new MongoClient(settings.ConnectionString);
        return client.GetDatabase(settings.DatabaseName);
    }

BookService.cs

public class BookService
{
    private readonly IMongoCollection<Book> _books;

    public BookService(IMongoCollection<Book> books)
    {
        _books = books;
    }

    public List<Book> Get() => _books.Find(book => true).ToList();
}

BooksController.cs

public class BooksController : ControllerBase
{
    private readonly BookService _bookService;

    public BooksController(BookService bookService)
    {
        _bookService = bookService;
    }

    [HttpGet]
    public ActionResult<List<Book>> Get() => _bookService.Get();
}

My use case: I have multiple databases and my API end point will accept database name as ONE of the argument

  [HttpGet]
    public ActionResult<List<Book>> Get(string dbName) => _bookService.Get(dbName);

Now question is what changes requires in my service class and ConfigureMongoDb method of startup class so that I can still get lazy initialization and singleton support?

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

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

发布评论

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

评论(1

空心↖ 2025-01-15 23:53:08

您可以创建一个可以根据数据库名称提供集合的类,而不是将 IMongoCollection 注入到服务中(BooksService,...),例如

public class MongoCollectionProvider
{
  private readonly IMongoClient _client;

  public MongoDbCollectionProvider(IMongoClient client) 
  {
    _client = client;
  }

  public IMongoCollection<T> GetCollection<T>(string database, string collection)
  {
    var db = _client.GetDatabase(database);
    return db.GetCollection<T>(collection);
  }
}

,您可以将此类注入到服务中并在查询数据库之前检索集合,例如,

public class BookService
{
    private readonly MongoCollectionProvider _prov;
    private readonly string _coll;

    public BookService(MongoCollectionProvider prov, string coll)
    {
        _prov = prov;
        _coll = coll;
    }

    public List<Book> Get(string dbName) => _prov.GetCollection<Book>(dbName, _coll).Find(book => true).ToList();
}

您可以像这样注册服务:

private void ConfigureMongoDb(IServiceCollection services)
{
  var settings = GetMongoDbSettings();
  services.AddSingleton(_ => CreateMongoClient(settings));
  services.AddSingleton<MongoCollectionProvider>();

  services.AddSingleton(sp => 
  {
    var prov = sp.GetRequiredService<MongoCollectionProvider>();
    return new AuthorsService(prov, settings.AuthorsCollectionName);
  }
  services.AddSingleton(sp => 
  {
    var prov = sp.GetRequiredService<MongoCollectionProvider>();
    return new BooksService(prov, settings.BooksCollectionName);
  }
}

private DatabaseSettings GetMongoDbSettings() => Configuration.GetSection(nameof(DatabaseSettings)).Get<DatabaseSettings>();

private static IMongoDatabase CreateMongoClient(DatabaseSettings settings)
{
  return new MongoClient(settings.ConnectionString);
}

如果您想将数据库限制为特定的数据库,您可以将 MongoCollectionProvider 更改为仅接受注册的数据库名称。

Instead of injecting the IMongoCollection into the services (BooksService, ...), you could create a class that can provide the collection based upon the database name, e.g.

public class MongoCollectionProvider
{
  private readonly IMongoClient _client;

  public MongoDbCollectionProvider(IMongoClient client) 
  {
    _client = client;
  }

  public IMongoCollection<T> GetCollection<T>(string database, string collection)
  {
    var db = _client.GetDatabase(database);
    return db.GetCollection<T>(collection);
  }
}

You can then inject this class into the services and retrieve the collection before querying the database, e.g.

public class BookService
{
    private readonly MongoCollectionProvider _prov;
    private readonly string _coll;

    public BookService(MongoCollectionProvider prov, string coll)
    {
        _prov = prov;
        _coll = coll;
    }

    public List<Book> Get(string dbName) => _prov.GetCollection<Book>(dbName, _coll).Find(book => true).ToList();
}

You can register the services like this:

private void ConfigureMongoDb(IServiceCollection services)
{
  var settings = GetMongoDbSettings();
  services.AddSingleton(_ => CreateMongoClient(settings));
  services.AddSingleton<MongoCollectionProvider>();

  services.AddSingleton(sp => 
  {
    var prov = sp.GetRequiredService<MongoCollectionProvider>();
    return new AuthorsService(prov, settings.AuthorsCollectionName);
  }
  services.AddSingleton(sp => 
  {
    var prov = sp.GetRequiredService<MongoCollectionProvider>();
    return new BooksService(prov, settings.BooksCollectionName);
  }
}

private DatabaseSettings GetMongoDbSettings() => Configuration.GetSection(nameof(DatabaseSettings)).Get<DatabaseSettings>();

private static IMongoDatabase CreateMongoClient(DatabaseSettings settings)
{
  return new MongoClient(settings.ConnectionString);
}

If you want to constrain the databases to specific ones, you can change the MongoCollectionProvider to only accept registered database names.

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