Repository 层
这一层就是把数据访问收进去。
先按最直接的理解来用:
- 查库放这里
- 落库放这里
- FreeSql 的使用也收在这里
业务规则别写在这里。
这一层通常放什么
最常见的有:
IDbSource的实现- Entity
- Repository
- 多表查询需要的映射对象
一个常见结构例如:
Repository
├── Entities
├── View
├── MappingDatas
└── Repositories
DbSource 是干什么的
先建一个实现 IDbSource 的类,把当前数据库连接标识出来。
public class AegisDb : IDbSource
{
public AegisDb(IFreeSql<AegisDb> sqlClient)
{
SqlClient = sqlClient;
}
public IFreeSql<AegisDb> SqlClient { get; }
}
这个类不用写复杂逻辑,它主要是给当前数据库连接一个明确的入口。
Entity 怎么写
Entity 是数据库表对应的实体。
常见写法:
- 类名以
Entity结尾 - 用
[Table]指定表名 - 主键用
[Column(IsPrimary = true)]
例如:
[Table(Name = "User")]
public class UserEntity
{
[Column(IsPrimary = true)]
public long Id { get; set; }
public string Name { get; set; }
}
Repository 怎么写
最常见的仓储类,就是继承 BaseRepository<TEntity, TId>。
public class UserRepository : BaseRepository<UserEntity, long>
{
public UserRepository(IFreeSql<AegisDb> fsql) : base(fsql)
{
}
public Task<UserEntity> GetByIdAsync(long id)
{
return this.Where(x => x.Id == id).FirstAsync();
}
}
第一版项目里,单表增删改查通常写到这里就够了。
Service 和 Repository 的边界
这一条别混:
- Repository 负责数据访问
- Service 负责业务流程
也就是说:
- Service 可以调 Repository
- Service 不要直接去碰
IFreeSql
什么时候需要 MappingData
如果是简单单表,Entity 通常就够。
如果是多表联查、结果又不适合直接回 DTO,可以先在 Repository 层建一个中间映射对象。
这类对象通常只服务于查询结果整理,不承担业务逻辑。
这一层最容易踩的坑
- 在 Repository 里写业务判断
- 在 Service 里直接查库
- Entity 和 DTO 混着用
- 仓储类越过边界去做接口层拼装
先做到什么程度就够
第一版项目里,这一层先做到下面这样就够了:
- 能定义
DbSource - 能定义一个 Entity
- 能写一个 Repository
- 能让 Service 通过 Repository 查出一条数据
等第一版稳定了,再继续补复杂查询、分页对象、多表映射这些东西。