it works ! But why am I obliged to add it ?
NotificationStore.InsertNotificationAsync calls SaveChangesAsync in using(_unitOfWorkManager.Current.SetTenantId(null)). That's because NotificationInfo is MultiTenancySides.Host.
Since your AccountingCode hasn't been saved, ApplyAbpConcepts will try to set its audit properties (i.e. TenantId = 0). An error is thrown in CheckAndSetMustHaveTenantIdProperty because AccountingCode is IMustHaveTenant.
Therefore, you should call SaveChanges before SendMessageAsync.
Note: (await UserManager.GetUserByIdAsync((long)AbpSession.UserId)).ToUserIdentifier() can be simplified to AbpSession.ToUserIdentifier()
What is the best way to remove all the other references to that Tenant? Should this just be a SQL script I need to generate?
Yes, you answered your own question with another question :)
The short answer is: You can't. You should use a domain service/manager instead. See detailed answers: Should I be calling an AppService from another AppService?
Thanks for letting us know!
I've added that solution to the same issue on GitHub: https://github.com/aspnetzero/aspnet-zero-core/issues/74
You cannot modify the method signature to be async as DoWork is called synchronously.
Wrap your await method calls in AsyncHelper.RunSync(() => AsyncMethod(...)) like this:
if (AsyncHelper.RunSync(() => SettingManager.GetSettingValueForTenantAsync<bool>(...)))
{
// ...
}
Thanks for letting us know!
In case anyone has the same issue, upgrade Z.EntityFramework.Extensions.EFCore to v2.0.8. Resolved here: https://github.com/zzzprojects/EntityFramework-Extensions/issues/63
Hi Tommy, can you try Abp.EntityFramework v2.3.0?
Do the users belong to the same tenant as the current user? If not, you need to disable the filter:
using (_unitOfWorkManager.Current.DisableFilter(AbpDataFilters.MayHaveTenant))
{
// ...
}
Yes, so it is currently possible for the next code to be calculated before an insert is completed.
A quick fix is to lock with a private static _syncObj:
private static readonly object _syncObj = new object();
public async Task<Sample> CreateNewSample(Sample sample)
{
// ...
lock (_syncObj)
{
AsyncHelper.RunSync(async () =>
{
sample.Line = await GetNextChildCodeAsync(sample.ParentSampleId);
// ...
var insertedSample = await _sampleRepository.InsertAsync(sample);
await CurrentUnitOfWork.SaveChangesAsync();
}
}
}
Note that:
A better alternative is to retrieve the next code from a singleton cache that has a lock, like in UserFriendsCache. Then, you can store the next code as a variable in the cache instead of reading from the database every time. You can try to implement that yourself.