AF Repository Refactor Skill
Overview
Refactor AntFlowCore service classes from directly extending AFBaseCurdRepositoryService<TEntity> (which tightly couples to IFreeSql) to using the IAntFlowRepositoryMix<TEntity, TRepo> pattern. This introduces a repository abstraction layer, making the codebase ORM-agnostic and easier to migrate to other ORMs.
Architecture Context
The project follows this layered structure:
AntFlowCore.Persist.api → Interface layer (service & repository interfaces)
AntFlowCore.Persist → Implementation layer (service & repository implementations)
AntFlowCore.AspNetCore → DI registration (ServiceRegistration.cs)
Key base types:
IBaseRepository<TEntity>— ORM-agnostic repository interface (inAntFlowCore.Abstraction.Orm.repository)RepositoryBase<TEntity>— FreeSql repository base implementation (inAntFlowCore.Abstraction.Orm.repository)AntFlowOrmContext— FreeSql context wrapper, injected intoRepositoryBaseconstructorsIAntFlowRepositoryMix<TEntity, TRepo>— Mixin interface exposing_repositoryproperty (inAntFlowCore.Persist.api.interf.repository)AFBaseCurdRepositoryService<TEntity>— Legacy base class tightly coupled to IFreeSql (to be eliminated)
Refactoring Workflow
For each service to refactor, follow these steps in order:
Step 1: Create Repository Interface
In src/AntFlowCore.Persist.api/interf/repository/, create I{EntityName}Repository.cs:
using AntFlowCore.Abstraction.Orm.repository;
using AntFlowCore.Base.entity; // entity namespace may vary
namespace AntFlowCore.Persist.api.interf.repository;
public interface I{EntityName}Repository : IBaseRepository<{EntityName}>
{
}
Check if the repository interface already exists before creating it.
Step 2: Create Repository Implementation
In src/AntFlowCore.Persist/repo/, create Fs{EntityName}Repository.cs:
using AntFlowCore.Abstraction.Orm.repository;
using AntFlowCore.Base.entity;
using AntFlowCore.Persist.api.interf.repository;
namespace antflowcore.conf.ef;
public class Fs{EntityName}Repository : RepositoryBase<{EntityName}>, I{EntityName}Repository
{
public Fs{EntityName}Repository(AntFlowOrmContext context) : base(context)
{
}
}
Check if the repository implementation already exists before creating it.
Step 3: Refactor Service Interface
Modify I{EntityName}Service in src/AntFlowCore.Persist.api/interf/repository/:
Before:
public interface I{EntityName}Service : IBaseRepositoryService<{EntityName}>
After:
using antflowcore.service.interf.repository;
public interface I{EntityName}Service : IAntFlowRepositoryMix<{EntityName}, I{EntityName}Repository>
Remove any using FreeSql; if no longer needed.
Step 4: Refactor Service Implementation
Modify {EntityName}Service in src/AntFlowCore.Persist/repository/:
Before:
public class {EntityName}Service : AFBaseCurdRepositoryService<{EntityName}>, I{EntityName}Service
{
public {EntityName}Service(IFreeSql freeSql) : base(freeSql) { }
// uses this.baseRepo.xxx
}
After:
public class {EntityName}Service : I{EntityName}Service
{
public {EntityName}Service(I{EntityName}Repository repository)
{
_repository = repository;
}
public I{EntityName}Repository _repository { get; }
// uses _repository.xxx
}
Step 5: Fix Callers (baseRepo → _repository migration)
Search the entire codebase for references to the old service's baseRepo property and convert them:
| Old Pattern | New Pattern |
|---|---|
service.baseRepo.Where(predicate).ToList() |
service._repository.Find(predicate) |
service.baseRepo.Where(predicate).First() |
service._repository.FirstOrDefault(predicate) |
service.baseRepo.Insert(entity) |
service._repository.Add(entity) |
service.baseRepo.Update(entity) |
service._repository.Update(entity) |
service.baseRepo.Delete(entity) |
service._repository.Remove(entity) |
service.baseRepo.Select.ToList() |
service._repository.GetAll() |
service._repository.GetQueryable().Where(predicate).ToList() |
service._repository.Find(predicate) |
service._repository.GetQueryable().Where(predicate).First() |
service._repository.FirstOrDefault(predicate) |
service._repository.GetQueryable().Count() |
service._repository.Count() |
Also check for callers that reference Frsql (IFreeSql property) on the service if it was exposed.
Step 6: Register Repository in DI
In src/AntFlowCore.AspNetCore/conf/di/serviceregistration/ServiceRegistration.cs, add the repository registration near the existing repository registrations (around the line with //=========):
services.AddSingleton<I{EntityName}Repository, Fs{EntityName}Repository>();
Insert it after the last existing repository registration, before the //================================= line.
Validation Checklist
After completing all steps, verify:
- No compilation errors in the refactored service
- No remaining references to
.baseRepoon the service type - Repository is registered in
ServiceRegistration.cs - The service no longer depends on
AFBaseCurdRepositoryServiceorIFreeSqldirectly - All callers updated to use
_repositoryinstead ofbaseRepo
Common Pitfalls
- Some services expose
IFreeSql Frsql { get; }— this also needs to be removed or replaced - Some callers use
ServiceProviderUtils.GetService<XxxService>()to get the service and then accessbaseRepo— these also need fixing - The
IAntFlowRepositoryMixinterface is in namespaceantflowcore.service.interf.repository(lowercase) — ensure correct using - Repository implementations go in namespace
antflowcore.conf.ef(lowercase) — match existing convention
Source: mrtylerzhou/AntFlow.net — distributed by TomeVault.