Service: Difference between revisions
(Created page with "Return to Programming Guide") |
No edit summary Tag: Manual revert |
||
(3 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
<strong>Create the interface:</strong> | |||
<pre>public interface IFooService : IGenericCrudService<Foo, FooDTO, int> | |||
{ | |||
Task GetList(PagedCollection<Foo> pagedCollection); | |||
}</pre> | |||
The IGenericCrudService provides the interface for create/update/delete methods. | |||
<strong>Create the implementation:</strong> | |||
<pre>public class FooService : GenericCrudService<Foo, FooDTO, int>, IFooService | |||
{ | |||
private readonly NOVUSContext dbContext; | |||
public FooService( | |||
IUnitOfWork uow, | |||
IMapper mapper, | |||
IHttpContextAccessor httpContextAccessor, | |||
ILogger<FooService> logger, | |||
IServiceHelper2 serviceHelper2, | |||
NOVUSContext dbContext | |||
) | |||
: base(uow, mapper, httpContextAccessor, logger, serviceHelper2) | |||
{ | |||
this.dbContext = dbContext; | |||
} | |||
// the AppendQueryParameters() method is optional and can be removed | |||
protected override IQueryable<Foo> AppendQueryParameters(IQueryable<Foo> query, QueryParameters queryParameters) | |||
{ | |||
foreach (KeyValuePair<string, ICollection<string>> keyValuePair in queryParameters.Params) | |||
{ | |||
if ("fooId".Equals(keyValuePair.Key, StringComparison.OrdinalIgnoreCase)) | |||
{ | |||
int fooId = Convert.ToInt32(keyValuePair.Value.First()); | |||
query = query.Where(p => p.FooId == fooId); | |||
} | |||
} | |||
return query; | |||
} | |||
public override async Task<Foo> GetEntityById(int id) | |||
=> await GetDbSet().FirstOrDefaultAsync(p => p.FooId == id); | |||
protected override DbContext GetDbContext() | |||
=> dbContext; | |||
protected override DbSet<Foo> GetDbSet() | |||
=> dbContext.Foo; | |||
protected override int GetEntityID(Foo entity) | |||
=> entity.FooId; | |||
protected override Expression<Func<Foo, bool>> GetEntityIDEqualityCheck(int id) | |||
=> p => p.FooId == id; | |||
public override async Task BeforeSavingNewEntity(Foo entity) | |||
{ | |||
} | |||
public override void UpdateEntityProperties(Foo entity, Foo withProperties) | |||
{ | |||
entity.Bar = withProperties.Bar; | |||
} | |||
public override async Task<BusinessResult> CheckBusinessKey(string value) | |||
{ | |||
BusinessResult result = new BusinessResult(); | |||
await CheckFooIdAvailability(value, result); | |||
return result; | |||
} | |||
private async Task<bool> CheckFooIdAvailability(string fooId, BusinessResult result) | |||
{ | |||
var available = !await dbContext.TESiteBuilding | |||
.AnyAsync(u => u.FooId == fooId); | |||
if (!available) | |||
{ | |||
result.ResultStatus = ResultStatus.Failure; | |||
result.Message = RsMessages.FooIdNotUnique; | |||
} | |||
return available; | |||
} | |||
protected override async Task<bool> ValidateCreate(BusinessResult result, Foo newEntity) | |||
{ | |||
if (!await CheckFooIdAvailability(newEntity.FooId, result)) | |||
{ | |||
return false; | |||
} | |||
return true; | |||
} | |||
protected override string AlreadyExistsErrorMessage | |||
{ | |||
get | |||
{ | |||
return "Foo already exists."; | |||
} | |||
} | |||
public async Task GetList(PagedCollection<Foo> pagedCollection) | |||
{ | |||
await dbContext.TESiteBuilding | |||
.AsNoTracking() | |||
.ToPagedCollectionAsync(pagedCollection); | |||
} | |||
}</pre> | |||
<strong>To prevent creating or updating a record,</strong> you can override the ValidateCreate() or ValidateUpdate() methods respectively. For example, here is an example of preventing the creation of a record: | |||
<pre>protected override async Task<bool> ValidateCreate( | |||
BusinessResult result, | |||
Foo newEntity | |||
) | |||
{ | |||
if (/* ... */) | |||
{ | |||
// set result message | |||
return false; | |||
} | |||
return true; | |||
}</pre> | |||
Return false to prevent the save. | |||
<strong>To include relationships,</strong> in your service implementation, modify: | |||
<pre>public override async Task<Foo> GetEntityByID(int id) | |||
=> await GetDbSet() | |||
.Include(p => p.ChildRecordCollection) | |||
.FirstOrDefaultAsync(p => p.FooId == id);</pre> | |||
This only affects the GetEntityById(ID id). For create, update, and deletes, override ModifyQueryBeforeFirstOrDefaultAsync() (introduced in user-story-124): | |||
protected override IQueryable<Foo> ModifyQueryBeforeFirstOrDefaultAsync(DbSet<Foo> dbSet) | |||
<pre>{ | |||
return dbSet.Include(p => p.ChildRecordCollection); | |||
}</pre> | |||
<strong>Register the service to the DI container.</strong> In the Novus.Web.Common is a class called RegisterLayerServices which contains an extension method that is called in the Startup class. In the registerBusinessLayer() method, add services.AddTransient<IFooService, FooService>(). | |||
Return to [[Programming Guide]] | Return to [[Programming Guide]] |
Latest revision as of 15:28, 10 October 2023
Create the interface:
public interface IFooService : IGenericCrudService<Foo, FooDTO, int> { Task GetList(PagedCollection<Foo> pagedCollection); }
The IGenericCrudService provides the interface for create/update/delete methods.
Create the implementation:
public class FooService : GenericCrudService<Foo, FooDTO, int>, IFooService { private readonly NOVUSContext dbContext; public FooService( IUnitOfWork uow, IMapper mapper, IHttpContextAccessor httpContextAccessor, ILogger<FooService> logger, IServiceHelper2 serviceHelper2, NOVUSContext dbContext ) : base(uow, mapper, httpContextAccessor, logger, serviceHelper2) { this.dbContext = dbContext; } // the AppendQueryParameters() method is optional and can be removed protected override IQueryable<Foo> AppendQueryParameters(IQueryable<Foo> query, QueryParameters queryParameters) { foreach (KeyValuePair<string, ICollection<string>> keyValuePair in queryParameters.Params) { if ("fooId".Equals(keyValuePair.Key, StringComparison.OrdinalIgnoreCase)) { int fooId = Convert.ToInt32(keyValuePair.Value.First()); query = query.Where(p => p.FooId == fooId); } } return query; } public override async Task<Foo> GetEntityById(int id) => await GetDbSet().FirstOrDefaultAsync(p => p.FooId == id); protected override DbContext GetDbContext() => dbContext; protected override DbSet<Foo> GetDbSet() => dbContext.Foo; protected override int GetEntityID(Foo entity) => entity.FooId; protected override Expression<Func<Foo, bool>> GetEntityIDEqualityCheck(int id) => p => p.FooId == id; public override async Task BeforeSavingNewEntity(Foo entity) { } public override void UpdateEntityProperties(Foo entity, Foo withProperties) { entity.Bar = withProperties.Bar; } public override async Task<BusinessResult> CheckBusinessKey(string value) { BusinessResult result = new BusinessResult(); await CheckFooIdAvailability(value, result); return result; } private async Task<bool> CheckFooIdAvailability(string fooId, BusinessResult result) { var available = !await dbContext.TESiteBuilding .AnyAsync(u => u.FooId == fooId); if (!available) { result.ResultStatus = ResultStatus.Failure; result.Message = RsMessages.FooIdNotUnique; } return available; } protected override async Task<bool> ValidateCreate(BusinessResult result, Foo newEntity) { if (!await CheckFooIdAvailability(newEntity.FooId, result)) { return false; } return true; } protected override string AlreadyExistsErrorMessage { get { return "Foo already exists."; } } public async Task GetList(PagedCollection<Foo> pagedCollection) { await dbContext.TESiteBuilding .AsNoTracking() .ToPagedCollectionAsync(pagedCollection); } }
To prevent creating or updating a record, you can override the ValidateCreate() or ValidateUpdate() methods respectively. For example, here is an example of preventing the creation of a record:
protected override async Task<bool> ValidateCreate( BusinessResult result, Foo newEntity ) { if (/* ... */) { // set result message return false; } return true; }
Return false to prevent the save.
To include relationships, in your service implementation, modify:
public override async Task<Foo> GetEntityByID(int id) => await GetDbSet() .Include(p => p.ChildRecordCollection) .FirstOrDefaultAsync(p => p.FooId == id);
This only affects the GetEntityById(ID id). For create, update, and deletes, override ModifyQueryBeforeFirstOrDefaultAsync() (introduced in user-story-124): protected override IQueryable<Foo> ModifyQueryBeforeFirstOrDefaultAsync(DbSet<Foo> dbSet)
{ return dbSet.Include(p => p.ChildRecordCollection); }
Register the service to the DI container. In the Novus.Web.Common is a class called RegisterLayerServices which contains an extension method that is called in the Startup class. In the registerBusinessLayer() method, add services.AddTransient<IFooService, FooService>().
Return to Programming Guide