微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决具有多个集合的ASP.NET Core Web API和MongoDB

我有与MongoDB交互的WebAPI。

我使用lazy approach将所有MongoDB集合类创建为单例。我知道这是一种“标准”方法,但是由于我将.NET Core用于我的Web API,因此我发现这个tutorial乍看之下描述了如何为.NET Core应用程序更有效地实现它。>

无论如何,它说明了如何使用一个数据库(仅包含一个集合)来进行此操作,这非常有限。

例如,对于2个集合,它似乎甚至已被弃用。例如this part of code

public BookService(IBookstoreDatabaseSettings settings)
{
    var client = new MongoClient(settings.ConnectionString);
    var database = client.GetDatabase(settings.DatabaseName);

    _books = database.GetCollection<Book>(settings.BooksCollectionName);
}

如果我的第二个集合使用相同的构造函数,它将创建MongoClient的新实例,MongoDB documentation不建议这样做:

建议将MongoClient实例存储为全局变量,既可以作为静态变量,也可以存储在具有单例寿命的IoC容器中。

然后我的问题是:是否有更好的方法将MongoDB与带有.NET Core的多个集合一起使用(某种连接this question),还是使用“通用惰性”方法更好?

解决方法

我认为Retic的方法还不错。

让我们继续他的回答,并将数据库配置提取到一个单独的方法ConfigureMongoDb中:

public void ConfigureServices(IServiceCollection services)
{
    ConfigureMongoDb(services);

    services.AddControllers()
        .AddNewtonsoftJson(options => options.UseMemberCasing());
}

private void ConfigureMongoDb(IServiceCollection services)
{
    var settings = GetMongoDbSettings();
    var db = CreateMongoDatabase(settings);

    var collectionA = db.GetCollection<Author>(settings.AuthorsCollectionName);
    services.AddSingleton(collectionA);
    services.AddSingleton<AuthorService>();

    var collectionB = db.GetCollection<Book>(settings.BooksCollectionName);
    services.AddSingleton(collectionB);
    services.AddSingleton<BookService>();
}

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

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

或更紧凑的形式:

private void ConfigureMongoDb(IServiceCollection services)
{
    var settings = GetMongoDbSettings();
    var db = CreateMongoDatabase(settings);

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

    void AddMongoDbService<TService,TModel>(string collectionName)
    {
        services.AddSingleton(db.GetCollection<TModel>(collectionName));
        services.AddSingleton(typeof(TService));
    }
}

这种方法的缺点是,所有与mongodb相关的实例(服务除外)都是在启动时创建的。 这并不总是不好的,因为在设置错误或其他错误的情况下,启动时会立即得到响应。

如果要对此实例进行延迟初始化,可以使用工厂方法注册数据库创建和集合检索:

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

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

在服务中,您只需要注入已注册的集合。

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

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

public class AuthorService
{
    private readonly IMongoCollection<Author> _authors;

    public AuthorService(IMongoCollection<Author> authors)
    {
        _authors = authors;
    }
}
,

您可以在“服务”容器中注册IMongoDatabase的单个实例。那么您可以使用IMongoDatabase实例将Singleton Collections添加到您的服务容器中。

var client = new MongoClient(connectionString);
var db = client.GetDatabase(dbName);
 
var collectionA = db.GetCollection<Model>(collectionName);
services.AddSingleton<IMongoDatabase,db>();
services.AddSingleton<IMongoCollection,collectionA>();

要使用这些功能,您将通过控制器构造函数将服务公开给控制器。

public class SomeController
{
   private readonly IMongoCollection<SomeModel> _someCollection;

   public SomeController(IMongoCollection<SomeModel> someCollection)
   {
      _someCollection = someCollection;
   }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。