我正在使用Mongodb构建带有ASP.NET核心的API,并且我拥有不同的服务,用户服务家庭服务等。我想知道我应该将每个服务注册为asp.net核心文档中提到的单例还是作为范围。链接到存储库https://github.com/krisk0su/apartments
UserService.cs
public class UserService
{
private readonly IMongoCollection<User> _books;
private readonly IPasswordHasher _passwordService;
public UserService(IBookstoreDatabaseSettings settings, IPasswordHasher passwordService)
{
var client = new MongoClient(settings.ConnectionString);
var database = client.GetDatabase(settings.DatabaseName);
_books = database.GetCollection<User>(settings.UsersCollectionName);
_passwordService = passwordService;
}
public List<User> Get() =>
_books
.Find(book => true)
.ToList();
public User Get(string id) =>
_books.Find(user => user.Id == id).FirstOrDefault();
public User Create(User user)
{
var password = this._passwordService.HashPassword(user.Password);
user.Password = password;
_books.InsertOne(user);
return user;
}
public void Update(string id, User bookIn) =>
_books.ReplaceOne(book => book.Id == id, bookIn);
public void Remove(User bookIn) =>
_books.DeleteOne(book => book.Id == bookIn.Id);
public void Remove(string id) =>
_books.DeleteOne(book => book.Id == id);
}
Startup.cs
services.AddSingleton<UserService>();
services.AddSingleton<BookService>();
services.AddSingleton<AuthenticationService>();
services.AddScoped<IPasswordHasher, PasswordHasher>();
答案 0 :(得分:4)
很复杂。
首先MongoClient
可以是singleton,因此所有使用MongoClient
的服务也可以是单例。它的重要原因是单例服务不能依赖寿命较短的服务(作用域,瞬态)。
现在介绍UserService
。它的所有相关性都是单例,并且服务本身不存储应该在有限的时间内生存的任何数据(没有字段,没有道具)或有关特定用户的任何数据等。
所以它可以是单例!
但是,如果您决定添加范围依赖或在其中存储任何数据:
public class UserService
{
private readonly IMongoCollection<User> users;
private readonly long userCount; //this one
public UserService(IBookstoreDatabaseSettings settings)
{
var client = new MongoClient(settings.ConnectionString);
var database = client.GetDatabase(settings.DatabaseName);
users = database.GetCollection<User>(settings.UsersCollectionName);
userCount = users.Find(_ => true).CountDocuments();
}
}
然后您必须使其至少具有作用范围。
在DI中将MongoClient
作为单身人士要容易得多:
services.AddSingleton<IMongoClient>(s =>
new MongoClient(Configuration.GetConnectionString("MongoDb"))
);
,然后在所有服务中使用它:
public class UserService
{
private readonly IMongoCollection<User> users;
public UserService(IMongoClient mongoClient)
{
var database = mongoClient.GetDatabase("DatabaseName");
users = database.GetCollection<User>(settings.UsersCollectionName);
}
}
或者,如果您仅在应用程序中使用一个数据库,则也可以将IMongoDatabase移至DI,这样就不必每次都在服务构造函数中获取它。
答案 1 :(得分:4)
版本2.10的MongoDB .NET Driver参考文档在Mongo Client Reference > Driver > Connecting部分的Re-use页上进行了解释,
建议将
MongoClient
实例存储为全局变量,既可以作为静态变量,也可以存储在具有单例寿命的IoC容器中。
关于Mongo数据库Re-use,它没有提到单例生命期,但确实说“ 是线程安全的,可以安全地存储在全球范围内”,所以我会解释这意味着,如果您的实现需要这样做,则可以将它安全地存储为一个单例,但是如果您希望拥有另一个生存期,则不必如此。
IMongoDatabase
提供的MongoClient
的实现是线程安全的,可以安全地全局存储或存储在IoC容器中。
关于Mongo Collection Re-use的问题是相同的:
IMongoCollection<TDocument>
最终提供的MongoClient
的实现是线程安全的,可以安全地全局存储或存储在IoC容器中。
所以我再次解释说,寿命的选择取决于您的特定要求。
似乎只有MongoClient
带有建议才能使用单例寿命。