Never mind - It's already there! :)
I'd just rip what you can out of ABP and modify it as needed.
One challenge might be your dbcontext doesn't know anything about AbpNotifications. Maybe add that class to your Core project, add it to your Context as a DbSet. I've never tried to lift one of these into ANZ from ABP, so YMMV.
Inject the repo into your worker, then get the database context. (Available for workers in the Applications domain, btw). With db context, you have a lot of flexibilty on how to address it.
If you want to do this across tenants, clear the tenant filter (you'll find that easily, just search this forum or see below) and do it in a unit of work.
Then just use linq to sql to delete.
I don't use BatchDeleteAsync, but it exists, but maybe something like this might work? (assuming you injected the repo as _notificationRepository.
I also noticed that the NotificationInfo class has a constant of AllTenantIds ('0") and an audited entity.
[UnitOfWork]
public async void purge(Int days = 7)
{
using (CurrentUnitOfWork.DisableFilter(AbpDataFilters.MayHaveTenant))
{
DateTime _n = Clock.Now.Date.AddDays(-1 * days); // 7 days prior to start of today be default
await _notificationRepository.BatchDeleteAsync(n => n.CreationTime < _n); // asta-la-vista
}
}
FWIW - I'd check the BatchDeleteAsync calls in ABP. Sometimes, I feel like ANZ and ABP db activity could be optimized a bit, in which case seeing if you could get your context to see the AbpNotifications table in your project, and manipulate it directly, might help.
In the end - I try and get such things as close to a simple sql call like "delete from AbpNotifications where CreationTime < x;"... which means something like https://docs.microsoft.com/en-us/ef/core/querying/raw-sql might be worth investigating.
If you go that route, I'd be interested to know if making your context aware of the that table worked.
HTH!
This looks cool!
Just curious - since Ionic is Angular based - wouldn't an angular version of the project be fairly straightfoward to port?
Also - do you use Native in your project?
Lastly - has anyone used https://github.com/thruthesky/abcframework to convert ANZ to a Cordova app?
FWIW - I ran into something similiar with DBContext and background jobs. I ended up putting my jobs in the Application project and was able to resolve.
Might be worth trying.
FWIW - I've sometimes had to go the logs in AppData to get the stack dump.
HTH
I'm not ANZ support - but I've found the best way is through abstraction and domain services.
For example - You could create a business logic class that does what you need. Entity relational logic, business rules, etc., and call that from the standard classes.
You may want to create more than one.
Then, in the scaffolded / default classes - you call your classes instead.
When you regen an entity or upgrade, you'll want to look at your changes - and carry over your changes.
In effect - based on advice I've gotten for a similar question - this was the advice I got.
As a simple example - in an app services createoredit method..You would copy createoredit, create, and edit to your class, and modify there, then, in the app service, inject your class and use the default methods to just wrap yours.
If you regen the entity, it will overwrite this, so you'll have to update the appservice methods to use yours instead.
It can be tedious, but I've found Checkin -> Scaffold / merge -> examine diff of all changed files and fix until it builds -> checkin to be a workable workflow.
I've actually suggested on GitHub that they leverage regions to carry over custom code.
One of my practices as well, is I use a custom region at the end of any file I know will be overwritten by the RAD tool. It makes carrying my changes over much easier, as I copy the start of that region to the end of the file to the end of the new file.
You can modify methods outright doing that if you want, then simply comment out the updated methods.
In the end, though - the advice to do a domain service has been my go to approach.
Of note - when creating domain services, where you put them matters; especially if you want to get to the DbContext. The documentation guides you to put them in Core, but I've begun to put more and more of them in the Application project.
The first project I did with ANZ, several years ago - I had a completely separate project in the solution - but I wouldn't recommend that approach now.
My only other bit of advice is not to move the files it generates. When you run the RAD tool, it'll simply recreate the file where it was, and if you've moved it, the build will fail and you'll have to unravel the issues.
One thing I really don't like about the project structure is how it dumps DTOs into one folder, instead of breaking them out for the appservice they're used by. They could all be in the same namespace, but grouping them by app service would be useful. Alas, that is unecessary.
I found this MS article - I will attempt to use this information to accomplish what I need to do.
hey dmux - have you looked at DeleteAllUserNotifications in NotificationAppService?
It hits the notification manager, which hits the notifcationstore, which has transient dependency. (all within ABP project).
IRepository<NotificationInfo, Guid> _notificationRepository;
namespace Abp.Domain.Repositories.
You can inject that into your job - maybe get you want you need.
In ABP project, check the NotificationStore in Abp.Zero.Common.
Yes, that's what I'm trying to figure out how to do.
Microsoft docs say:
Join<TOuter,TInner,TKey,TResult>(IEnumerable<TOuter>, IEnumerable<TInner>, Func<TOuter,TKey>, Func<TInner,TKey>, Func<TOuter,TInner,TResult>)
I found this example on Stack Overflow which looks promising: https://stackoverflow.com/questions/19644617/linq-multiple-join-iqueryable-modify-result-selector-expression
here's what I am doing for now:
var uId = AbpSession.UserId;
var depList = (from ed in _employeeDepartmentRepository.GetAll()
join du in _departmentUserRepository.GetAll() on ed.DepartmentId equals du.DepartmentId
where du.UserId == uId
select ed.EmployeeId).ToList();
var query = _lookup_employeeRepository.GetAll()
.WhereIf(
!string.IsNullOrWhiteSpace(input.Filter), e =>
e.firstName.Contains(input.Filter) || e.lastName.Contains(input.Filter)
)
.Where(e => depList.Contains(e.Id));
Not the most elegant, and it hits the database twice.
Ultimately, I may have to avoid using WhereIf and just test if there's a filter and create one or two queries.
Something like:
If input.filter then Query with a filter else Query without a filter
So, the reason one might want to use HandFire over the built in background jobs is granularity of control?