ASP.NET 核心 Web API 和 MongoDB 具有多个集合和多个数据库
ASP.NET Core Web API and MongoDB with multiple Collections and multiple Databases
有了这个问题 ASP.NET Core Web API and MongoDB with multiple Collections 的回答,我可以看到 mongodb 的 WITH
single 数据库完美使用单例和惰性初始化和 多个 集合。
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 端点将接受 database name
作为参数之一
[HttpGet]
public ActionResult<List<Book>> Get(string dbName) => _bookService.Get(dbName);
现在的问题是,我的 service
class 和 ConfigureMongoDb
启动方法 class 需要做哪些更改,以便我仍然可以获得惰性初始化和单例支持?
您可以创建一个 class 来提供基于数据库名称的集合,而不是将 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);
}
}
然后您可以将此 class 注入服务并在查询数据库之前检索集合,例如
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 更改为仅接受已注册的数据库名称。
有了这个问题 ASP.NET Core Web API and MongoDB with multiple Collections 的回答,我可以看到 mongodb 的 WITH
single 数据库完美使用单例和惰性初始化和 多个 集合。
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 端点将接受 database name
作为参数之一
[HttpGet]
public ActionResult<List<Book>> Get(string dbName) => _bookService.Get(dbName);
现在的问题是,我的 service
class 和 ConfigureMongoDb
启动方法 class 需要做哪些更改,以便我仍然可以获得惰性初始化和单例支持?
您可以创建一个 class 来提供基于数据库名称的集合,而不是将 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);
}
}
然后您可以将此 class 注入服务并在查询数据库之前检索集合,例如
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 更改为仅接受已注册的数据库名称。