Merge remote-tracking branch 'origin/Translate' into Translate

pull/613/head
梁士伟 6 years ago
commit 9e5b260880

@ -1,6 +1,6 @@
## 在AspNet Core MVC Web Application中使用ABP
本教程将介绍如何开始以最少的依赖关系开始使用ABP开发. You generally want to start with a ***[startup template](https://abp.io/Templates)***
本教程将介绍如何开始以最少的依赖关系开始使用ABP开发.
通常情况下你需要下载一个 ***[启动模板](https://abp.io/Templates)***
@ -158,4 +158,4 @@ services.AddApplication<AppModule>(options =>
### 源码
从[此处](../samples/BasicAspNetCoreApplication)获取本教程中创建的示例项目的源代码.
从[此处](../samples/BasicAspNetCoreApplication)获取本教程中创建的示例项目的源代码.

@ -95,4 +95,234 @@ services.AddMongoDbContext<MyDbContext>(options =>
});
```
现在可以在你的服务中注入并使用`IRepository<TEntity>` 或 `IQueryableRepository<TEntity>`了.
现在可以在你的服务中注入并使用`IRepository<TEntity>` 或 `IQueryableRepository<TEntity>`了.比如你有一个主键类型为`Guid`的`Book`实体:
```csharp
public class Book : AggregateRoot<Guid>
{
public string Name { get; set; }
public BookType Type { get; set; }
}
```
(`BookType`是个枚举)你想在[领域服务](Domain-Services.md)中创建一个`Book`实体:
```csharp
public class BookManager : DomainService
{
private readonly IRepository<Book, Guid> _bookRepository;
public BookManager(IRepository<Book, Guid> bookRepository) //注入默认的仓储
{
_bookRepository = bookRepository;
}
public async Task<Book> CreateBook(string name, BookType type)
{
Check.NotNullOrWhiteSpace(name, nameof(name));
var book = new Book
{
Id = GuidGenerator.Create(),
Name = name,
Type = type
};
await _bookRepository.InsertAsync(book);
//使用仓储中的方法
return book;
}
}
```
这是一个使用`InsertAsync`方法将一个实体插入到数据库的例子.
#### 添加自定义仓储
大多数情况下默认的泛型仓储已经足够用了(因为它们实现了`IQueryable`).然而,你可能需要创建自定义的仓库并添加自己的仓储方法.
比如你想要通过books类型删除书籍.建议像下面这样为你的仓储定义一个接口:
```csharp
public interface IBookRepository : IRepository<Book, Guid>
{
Task DeleteBooksByType(
BookType type,
CancellationToken cancellationToken = default(CancellationToken)
);
}
```
通常你希望从`IRepository`中继承标准的仓储方法.其实,你不必那么做.仓储接口定义在领域层,在数据层/基础设施层实现.([启动模板](https://abp.io/Templates)中的`MongoDB`项目)
实现`IBookRepository`接口的例子:
```csharp
public class BookRepository :
MongoDbRepository<BookStoreMongoDbContext, Book, Guid>,
IBookRepository
{
public BookRepository(IMongoDbContextProvider<BookStoreMongoDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public async Task DeleteBooksByType(
BookType type,
CancellationToken cancellationToken = default(CancellationToken))
{
await Collection.DeleteManyAsync(
Builders<Book>.Filter.Eq(b => b.Type, type),
cancellationToken
);
}
}
```
现在,就能在需要的时候[注入](Dependency-Injection.md)`IBookRepository`并使用`DeleteBooksByType`方法了.
##### 重写默认的泛型仓储
即使你创建了自定义仓储,你仍然可以注入默认的泛型仓储(本例中的`IRepository<Book, Guid>`).默认的仓储实现不会使用你创建的类.
如果你想用自定义的仓储替换默认的仓储实现,在`AddMongoDbContext`中做:
```csharp
context.Services.AddMongoDbContext<BookStoreMongoDbContext>(options =>
{
options.AddDefaultRepositories();
options.AddRepository<Book, BookRepository>(); //替换 IRepository<Book, Guid>
});
```
当你想**重写基础仓储方法**时,这一点尤为重要.例如,你想要重写`DeleteAsync`方法,以便更有效的删除实体:
```csharp
public override async Task DeleteAsync(
Guid id,
bool autoSave = false,
CancellationToken cancellationToken = default)
{
//TODO: 自定义实现删除方法
}
```
#### 访问MongoDB API
大多数情况下,你想要将MongoDB API隐藏在仓储后面(这是仓储的主要目的).如果你想在仓储之上访问MongoDB API,你可以使用`GetDatabase()`或`GetCollection()`方法.例如:
```csharp
public class BookService
{
private readonly IRepository<Book, Guid> _bookRepository;
public BookService(IRepository<Book, Guid> bookRepository)
{
_bookRepository = bookRepository;
}
public void Foo()
{
IMongoDatabase database = _bookRepository.GetDatabase();
IMongoCollection<Book> books = _bookRepository.GetCollection();
}
}
```
> 重要:如果你想访问MongoDB API,你需要在你的项目中引用`Volo.Abp.MongoDB`.这会破坏封装,但在这种情况下,这就是你想要的.
#### 高级主题
##### 设置默认的仓储类
默认的泛型仓储默认被`MongoDbRepository`类实现.你可以创建自己的实现并在默认的仓储中使用.
首先,像下面这样定义你的仓储类:
```csharp
public class MyRepositoryBase<TEntity>
: MongoDbRepository<BookStoreMongoDbContext, TEntity>
where TEntity : class, IEntity
{
public MyRepositoryBase(IMongoDbContextProvider<BookStoreMongoDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
}
public class MyRepositoryBase<TEntity, TKey>
: MongoDbRepository<BookStoreMongoDbContext, TEntity, TKey>
where TEntity : class, IEntity<TKey>
{
public MyRepositoryBase(IMongoDbContextProvider<BookStoreMongoDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
}
```
第一个是[复合主键的实体](Entities.md),第二个是只有一个主键的实体.
如果需要重写方法建议继承`MongoDbRepository`类,否则,你需要手动实现所有的仓储方法.
现在,你可以使用`SetDefaultRepositoryClasses`:
```csharp
context.Services.AddMongoDbContext<BookStoreMongoDbContext>(options =>
{
options.SetDefaultRepositoryClasses(
typeof(MyRepositoryBase<,>),
typeof(MyRepositoryBase<>)
);
//...
});
```
##### 为默认的仓储设置基类或接口
如果你的MongoDbContext继承自另一个MongoDbContext或者实现了某个接口,你可以使用这个基类或者接口作为默认仓储的类型.如:
```csharp
public interface IBookStoreMongoDbContext : IAbpMongoDbContext
{
Collection<Book> Books { get; }
}
```
`IBookStoreMongoDbContext`被`BookStoreMongoDbContext`类实现.然后你就可以在`AddDefaultRepositories`中使用:
```csharp
context.Services.AddMongoDbContext<BookStoreMongoDbContext>(options =>
{
options.AddDefaultRepositories<IBookStoreMongoDbContext>();
//...
});
```
现在,你自定义的`BookRepository`类也可以使用`IBookStoreMongoDbContext`接口:
```csharp
public class BookRepository
: MongoDbRepository<IBookStoreMongoDbContext, Book, Guid>,
IBookRepository
{
//...
}
```
为MongoDbContext使用接口的优点就是它可以被另一个实现替换.
##### 替换其他的DbContexts
一旦你正确定义并为MongoDbContext使用了接口,其他的实现就可以使用`ReplaceDbContext`来替换:
```csharp
context.Services.AddMongoDbContext<OtherMongoDbContext>(options =>
{
//...
options.ReplaceDbContext<IBookStoreMongoDbContext>();
});
```
这个例子中,`OtherMongoDbContext`实现了`IBookStoreMongoDbContext`.这个特性允许你在发开的时候使用多个MongoDbContext(每个模块一个),但是运行的时候只能使有一个MongoDbContext(实现所有MongoDbContexts的所有接口)
Loading…
Cancel
Save