This commit is contained in:
2020-01-27 19:39:00 +00:00
parent 3b2189de01
commit aac23818fb
17 changed files with 151 additions and 151 deletions

View File

@@ -8,7 +8,7 @@ TODO: Ensure scaleability by checking for performance issues now before replicat
- As per this document https://docs.microsoft.com/en-us/aspnet/core/performance/performance-best-practices?view=aspnetcore-3.1
- For scaleability go back to async only for any db calls functions like creating widgets etc
TODO: look for any line of code that does this or similar: await Task.CompletedTask;
TODO: look for any line of code that does this or similar: await Task.CompletedTask, [anything].Result;
- Needs to be turned into a true async function or not an async function
TODO: Look at any of my middleware code as it's a HOT PATH, make sure it's async db access etc and nothing slowing it down

View File

@@ -187,7 +187,7 @@ namespace AyaNova.Api.Controllers
if (!badRequest)
{
//check if object exists
if (!BizObjectExistsInDatabase.Exists(attachToObject))
if (!await BizObjectExistsInDatabase.ExistsAsync(attachToObject))
{
badRequest = true;
errorMessage = "Invalid attach object";
@@ -230,13 +230,13 @@ namespace AyaNova.Api.Controllers
});
//EVENT LOG
EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, attachToObject.ObjectId, attachToObject.ObjectType, AyaEvent.AttachmentCreate, v.DisplayFileName), ct);
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, attachToObject.ObjectId, attachToObject.ObjectType, AyaEvent.AttachmentCreate, v.DisplayFileName), ct);
//SEARCH INDEXING
// Search.ProcessNewObjectKeywords( UserLocaleIdFromContext.Id(HttpContext.Items), v.Id, AyaType.FileAttachment, v.DisplayFileName, v.DisplayFileName, v.Notes, v.StoredFileName);
var SearchParams = new Search.SearchIndexProcessObjectParameters(UserLocaleIdFromContext.Id(HttpContext.Items), v.Id, AyaType.FileAttachment, v.DisplayFileName);
SearchParams.AddText(v.Notes).AddText(v.DisplayFileName).AddText(v.StoredFileName);
Search.ProcessNewObjectKeywordsAsync(SearchParams);
await Search.ProcessNewObjectKeywordsAsync(SearchParams);
}
}
@@ -303,10 +303,10 @@ namespace AyaNova.Api.Controllers
FileUtil.deleteFileAttachment(dbObj, ct);
//Event log process delete
EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.AttachToObjectId, dbObj.AttachToObjectType, AyaEvent.AttachmentDelete, dbObj.DisplayFileName), ct);
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.AttachToObjectId, dbObj.AttachToObjectType, AyaEvent.AttachmentDelete, dbObj.DisplayFileName), ct);
//Delete search index
Search.ProcessDeletedObjectKeywordsAsync(dbObj.Id, AyaType.FileAttachment);
await Search.ProcessDeletedObjectKeywordsAsync(dbObj.Id, AyaType.FileAttachment);
return NoContent();
}
@@ -385,7 +385,7 @@ namespace AyaNova.Api.Controllers
}
//Log
EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.AttachToObjectId, dbObj.AttachToObjectType, AyaEvent.AttachmentDownload, dbObj.DisplayFileName), ct);
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.AttachToObjectId, dbObj.AttachToObjectType, AyaEvent.AttachmentDownload, dbObj.DisplayFileName), ct);
return PhysicalFile(filePath, mimetype, dbObj.DisplayFileName);

View File

@@ -123,7 +123,7 @@ namespace AyaNova.Api.Controllers
try
{
if (!biz.Put(o, inObj))
if (!await biz.PutAsync(o, inObj))
return BadRequest(new ApiErrorResponse(biz.Errors));
}
catch (DbUpdateConcurrencyException)
@@ -194,7 +194,7 @@ namespace AyaNova.Api.Controllers
if (!Authorized.HasDeleteRole(HttpContext.Items, biz.BizType))
return StatusCode(403, new ApiNotAuthorizedResponse());
if (!biz.Delete(o))
if (!await biz.DeleteAsync(o))
return BadRequest(new ApiErrorResponse(biz.Errors));
return NoContent();

View File

@@ -122,7 +122,7 @@ namespace AyaNova.Api.Controllers
try
{
if (!biz.Put(o, inObj, DataList))
if (!biz.PutAsync(o, inObj, DataList))
return BadRequest(new ApiErrorResponse(biz.Errors));
}
catch (DbUpdateConcurrencyException)
@@ -168,7 +168,7 @@ namespace AyaNova.Api.Controllers
if (!Authorized.HasDeleteRole(HttpContext.Items, biz.BizType))
return StatusCode(403, new ApiNotAuthorizedResponse());
if (!biz.Delete(o))
if (!biz.DeleteAsync(o))
return BadRequest(new ApiErrorResponse(biz.Errors));
return NoContent();

View File

@@ -165,7 +165,7 @@ namespace AyaNova.Api.Controllers
try
{
if (!biz.Put(o, inObj))
if (!biz.PutAsync(o, inObj))
return BadRequest(new ApiErrorResponse(biz.Errors));
}
catch (DbUpdateConcurrencyException)

View File

@@ -124,7 +124,7 @@ namespace AyaNova.Api.Controllers
LocaleBiz biz = LocaleBiz.GetBiz(ct, HttpContext);
//LocaleBiz biz = new LocaleBiz(ct, UserIdFromContext.Id(HttpContext.Items), UserRolesFromContext.Roles(HttpContext.Items));
var l = biz.LocaleKeyCoverage();
var l = biz.LocaleKeyCoverageAsync();
return Ok(ApiOkResponse.Response(l, true));
}
#endif
@@ -238,7 +238,7 @@ namespace AyaNova.Api.Controllers
}
catch (DbUpdateConcurrencyException)
{
if (!biz.LocaleItemExists(inObj.Id))
if (!biz.LocaleItemExistsAsync(inObj.Id))
{
return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND));
}
@@ -301,7 +301,7 @@ namespace AyaNova.Api.Controllers
}
catch (DbUpdateConcurrencyException)
{
if (!biz.LocaleExists(inObj.Id))
if (!biz.LocaleExistsAsync(inObj.Id))
{
return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND));
}
@@ -355,7 +355,7 @@ namespace AyaNova.Api.Controllers
//Instantiate the business object handler
//LocaleBiz biz = new LocaleBiz(ct, UserIdFromContext.Id(HttpContext.Items), UserRolesFromContext.Roles(HttpContext.Items));
LocaleBiz biz = LocaleBiz.GetBiz(ct, HttpContext);
if (!biz.Delete(dbObj))
if (!biz.DeleteAsync(dbObj))
{
return BadRequest(new ApiErrorResponse(biz.Errors));
}

View File

@@ -439,7 +439,7 @@ namespace AyaNova
//Ensure locales are present, not missing any keys and that there is a server default locale that exists
LocaleBiz lb = new LocaleBiz(dbContext, 1, ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE_ID, AuthorizationRoles.OpsAdminFull);
lb.ValidateLocales();
lb.ValidateLocalesAsync();

View File

@@ -1,12 +1,6 @@
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.JsonPatch;
using EnumsNET;
using AyaNova.Util;
using AyaNova.Api.ControllerHelpers;
using AyaNova.Biz;
using AyaNova.Models;
@@ -20,14 +14,14 @@ namespace AyaNova.Biz
{
//THIS IS THE METHOD CALLED BY THE ATTACHMENT CONTROLLER
internal static async Task<bool> Exists(AyaTypeId tid)
internal static async Task<bool> ExistsAsync(AyaTypeId tid)
{
return await Exists(tid.ObjectType, tid.ObjectId);
return await ExistsAsync(tid.ObjectType, tid.ObjectId);
}
//Returns existance status of object type and id specified in database
internal static bool Exists(AyaType aytype, long id, AyContext ct = null)
internal static async Task<bool> ExistsAsync(AyaType aytype, long id, AyContext ct = null)
{
//new up a context??
if (ct == null)
@@ -37,22 +31,20 @@ namespace AyaNova.Biz
switch (aytype)
{
case AyaType.User:
return ct.User.Any(m => m.Id == id);
return await ct.User.AnyAsync(m => m.Id == id);
case AyaType.Widget:
return ct.Widget.Any(m => m.Id == id);
return await ct.Widget.AnyAsync(m => m.Id == id);
case AyaType.FileAttachment:
return ct.FileAttachment.Any(m => m.Id == id);
return await ct.FileAttachment.AnyAsync(m => m.Id == id);
case AyaType.DataListFilter:
return ct.DataListFilter.Any(m => m.Id == id);
return await ct.DataListFilter.AnyAsync(m => m.Id == id);
case AyaType.DataListTemplate:
return ct.DataListTemplate.Any(m => m.Id == id);
return await ct.DataListTemplate.AnyAsync(m => m.Id == id);
case AyaType.FormCustom:
return ct.FormCustom.Any(m => m.Id == id);
return await ct.FormCustom.AnyAsync(m => m.Id == id);
default:
throw new System.NotSupportedException($"AyaNova.Biz.BizObjectExistsInDatabase::Exists type {aytype.ToString()} is not supported");
throw new System.NotSupportedException($"AyaNova.Biz.BizObjectExistsInDatabase::ExistsAsync type {aytype.ToString()} is not supported");
}
}

View File

@@ -49,7 +49,7 @@ namespace AyaNova.Biz
//CREATE
internal async Task<DataListFilter> CreateAsync(DataListFilter inObj)
{
Validate(inObj, true);
await ValidateAsync(inObj, true);
if (HasErrors)
return null;
else
@@ -65,7 +65,7 @@ namespace AyaNova.Biz
//Handle child and associated items:
//EVENT LOG
EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, outObj.Id, BizType, AyaEvent.Created), ct);
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, outObj.Id, BizType, AyaEvent.Created), ct);
//SEARCH INDEXING
// Search.ProcessNewObjectKeywords(UserLocaleId, outObj.Id, BizType, outObj.Name, outObj.Name);
@@ -77,9 +77,9 @@ namespace AyaNova.Biz
////////////////////////////////////////////////////////////////////////////////////////////////
//CREATE
internal DataListFilter Create(AyContext TempContext, DataListFilter inObj)
internal async Task<DataListFilter> Create(AyContext ct, DataListFilter inObj)
{
Validate(inObj, true);
await ValidateAsync(inObj, true);
if (HasErrors)
return null;
else
@@ -89,13 +89,13 @@ namespace AyaNova.Biz
outObj.UserId = UserId;
TempContext.DataListFilter.Add(outObj);
TempContext.SaveChanges();
await ct.DataListFilter.AddAsync(outObj);
await ct.SaveChangesAsync();
//Handle child and associated items:
//EVENT LOG
EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, outObj.Id, BizType, AyaEvent.Created), TempContext);
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, outObj.Id, BizType, AyaEvent.Created), ct);
//SEARCH INDEXING
// Search.ProcessNewObjectKeywords(UserLocaleId, outObj.Id, BizType, outObj.Name, outObj.Name);
@@ -116,7 +116,7 @@ namespace AyaNova.Biz
if (ret != null)
{
//Log
EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, fetchId, BizType, AyaEvent.Retrieved), ct);
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, fetchId, BizType, AyaEvent.Retrieved), ct);
}
return ret;
}
@@ -158,7 +158,7 @@ namespace AyaNova.Biz
//
//put
internal bool Put(DataListFilter dbObj, DataListFilter inObj)
internal async Task<bool> PutAsync(DataListFilter dbObj, DataListFilter inObj)
{
//preserve the owner ID if none was specified
if (inObj.UserId == 0)
@@ -170,12 +170,13 @@ namespace AyaNova.Biz
//this will allow EF to check it out
ct.Entry(dbObj).OriginalValues["ConcurrencyToken"] = inObj.ConcurrencyToken;
Validate(dbObj, false);
await ValidateAsync(dbObj, false);
if (HasErrors)
return false;
await ct.SaveChangesAsync();
//Log modification and save context
EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.Id, BizType, AyaEvent.Modified), ct);
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.Id, BizType, AyaEvent.Modified), ct);
//Update keywords
// Search.ProcessUpdatedObjectKeywords(UserLocaleId, dbObj.Id, BizType, dbObj.Name, dbObj.Name);
@@ -187,22 +188,24 @@ namespace AyaNova.Biz
////////////////////////////////////////////////////////////////////////////////////////////////
//DELETE
//
internal bool Delete(DataListFilter dbObj)
internal async Task<bool> DeleteAsync(DataListFilter dbObj)
{
//Determine if the object can be deleted, do the deletion tentatively
//Probably also in here deal with tags and associated search text etc
ValidateCanDelete(dbObj);
//FUTURE POSSIBLE NEED
//ValidateCanDelete(dbObj);
if (HasErrors)
return false;
ct.DataListFilter.Remove(dbObj);
ct.SaveChanges();
await ct.SaveChangesAsync();
//Delete sibling objects
//Event log process delete
EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObj.Id, dbObj.Name, ct);
ct.SaveChanges();
await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObj.Id, dbObj.Name, ct);
//Delete search index
//Search.ProcessDeletedObjectKeywords(dbObj.Id, BizType);
@@ -216,7 +219,7 @@ namespace AyaNova.Biz
//
//Can save or update?
private void Validate(DataListFilter inObj, bool isNew)
private async Task ValidateAsync(DataListFilter inObj, bool isNew)
{
//UserId required
@@ -240,7 +243,7 @@ namespace AyaNova.Biz
if (!PropertyHasErrors("Name"))
{
//Use Any command is efficient way to check existance, it doesn't return the record, just a true or false
if (ct.DataListFilter.Any(m => m.Name == inObj.Name && m.Id != inObj.Id))
if (await ct.DataListFilter.AnyAsync(m => m.Name == inObj.Name && m.Id != inObj.Id))
{
AddError(ApiErrorCode.VALIDATION_NOT_UNIQUE, "Name");
}
@@ -387,11 +390,11 @@ namespace AyaNova.Biz
}
//Can delete?
private void ValidateCanDelete(DataListFilter inObj)
{
//Leaving this off for now
}
//FOR FUTURE
// private void ValidateCanDelete(DataListFilter inObj)
// {
// //Leaving this off for now
// }

View File

@@ -56,7 +56,7 @@ namespace AyaNova.Biz
if (log)
{
//Log
EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, ret.Id, BizType, AyaEvent.Retrieved), ct);
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, ret.Id, BizType, AyaEvent.Retrieved), ct);
}
return ret;
}
@@ -68,7 +68,7 @@ namespace AyaNova.Biz
//
//put
internal bool Put(DataListTemplate dbObj, DataListTemplate inObj, IAyaDataList dataList)
internal async Task<bool> PutAsync(DataListTemplate dbObj, DataListTemplate inObj, IAyaDataList dataList)
{
//Replace the db object with the PUT object
@@ -84,8 +84,10 @@ namespace AyaNova.Biz
if (HasErrors)
return false;
await ct.SaveChangesAsync();
//Log modification and save context
EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.Id, BizType, AyaEvent.Modified), ct);
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.Id, BizType, AyaEvent.Modified), ct);
return true;
}
@@ -94,14 +96,14 @@ namespace AyaNova.Biz
////////////////////////////////////////////////////////////////////////////////////////////////
//DELETE
//
internal bool Delete(DataListTemplate dbObj)
internal async Task<bool> DeleteAsync(DataListTemplate dbObj)
{
//no validation required, we have defaults so this is ok anytime
ct.DataListTemplate.Remove(dbObj);
ct.SaveChanges();
await ct.SaveChangesAsync();
//Event log process delete
EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObj.Id, dbObj.DataListKey, ct);
ct.SaveChanges();
await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObj.Id, dbObj.DataListKey, ct);
return true;
}

View File

@@ -55,7 +55,7 @@ namespace AyaNova.Biz
//CREATE
internal async Task<FormCustom> CreateAsync(FormCustom inObj)
{
Validate(inObj, true);
await ValidateAsync(inObj, true);
if (HasErrors)
return null;
else
@@ -71,7 +71,7 @@ namespace AyaNova.Biz
//Handle child and associated items:
//EVENT LOG
EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, outObj.Id, BizType, AyaEvent.Created), ct);
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, outObj.Id, BizType, AyaEvent.Created), ct);
//SEARCH INDEXING
// Search.ProcessNewObjectKeywords(UserLocaleId, outObj.Id, BizType, outObj.Name, outObj.Name);
@@ -125,7 +125,7 @@ namespace AyaNova.Biz
//
//put
internal bool Put(FormCustom dbObj, FormCustom inObj)
internal async Task<bool> PutAsync(FormCustom dbObj, FormCustom inObj)
{
//Replace the db object with the PUT object
@@ -134,14 +134,15 @@ namespace AyaNova.Biz
//this will allow EF to check it out
ct.Entry(dbObj).OriginalValues["ConcurrencyToken"] = inObj.ConcurrencyToken;
Validate(dbObj, false);
await ValidateAsync(dbObj, false);
if (HasErrors)
return false;
dbObj.Template = JsonUtil.CompactJson(dbObj.Template);
await ct.SaveChangesAsync();
//Log modification and save context
EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.Id, BizType, AyaEvent.Modified), ct);
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.Id, BizType, AyaEvent.Modified), ct);
//Update keywords
// Search.ProcessUpdatedObjectKeywords(UserLocaleId, dbObj.Id, BizType, dbObj.Name, dbObj.Name);
@@ -157,7 +158,7 @@ namespace AyaNova.Biz
//
//Can save or update?
private void Validate(FormCustom inObj, bool isNew)
private async Task ValidateAsync(FormCustom inObj, bool isNew)
{
//FormKey required and must be valid
@@ -179,7 +180,7 @@ namespace AyaNova.Biz
if (!PropertyHasErrors("FormKey") && isNew)
{
//Use Any command is efficient way to check existance, it doesn't return the record, just a true or false
if (ct.FormCustom.Any(m => m.FormKey == inObj.FormKey && m.Id != inObj.Id))
if (await ct.FormCustom.AnyAsync(m => m.FormKey == inObj.FormKey && m.Id != inObj.Id))
{
AddError(ApiErrorCode.VALIDATION_NOT_UNIQUE, "FormKey");
}

View File

@@ -338,7 +338,7 @@ namespace AyaNova.Biz
//////////////////////////////////////////////////////////////////
//UTILITIES
internal static void LogEventCreatedModifiedEvents(JObject j, List<ImportAyaNova7MapItem> importMap, AyaType ayaType, AyContext ct)
internal static async Task LogEventCreatedModifiedEventsAsync(JObject j, List<ImportAyaNova7MapItem> importMap, AyaType ayaType, AyContext ct)
{
var V7Id = new Guid(j["ID"].Value<string>());
var RavenId = importMap.Where(m => m.V7ObjectId == V7Id).First().NewObjectAyaTypeId.ObjectId;
@@ -349,9 +349,9 @@ namespace AyaNova.Biz
//handle EventLog entries for users now that we have the user's created
//Created
EventLogProcessor.LogEventToDatabaseAsync(new Event(Creator, RavenId, ayaType, AyaEvent.Created, Created), ct);
await EventLogProcessor.LogEventToDatabaseAsync(new Event(Creator, RavenId, ayaType, AyaEvent.Created, Created), ct);
//MODIFIED
EventLogProcessor.LogEventToDatabaseAsync(new Event(Modifier, RavenId, ayaType, AyaEvent.Modified, Modified), ct);
await EventLogProcessor.LogEventToDatabaseAsync(new Event(Modifier, RavenId, ayaType, AyaEvent.Modified, Modified), ct);
}

View File

@@ -50,11 +50,11 @@ namespace AyaNova.Biz
{
//make sure sourceid exists
if (!LocaleExists(inObj.Id))
if (!await LocaleExistsAsync(inObj.Id))
AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "Id", "Source locale id does not exist");
//Ensure name is unique and not too long and not empty
ValidateAsync(inObj.Name, true);
await ValidateAsync(inObj.Name, true);
if (HasErrors)
return null;
@@ -74,10 +74,10 @@ namespace AyaNova.Biz
}
//Add it to the context so the controller can save it
ct.Locale.Add(NewLocale);
await ct.Locale.AddAsync(NewLocale);
await ct.SaveChangesAsync();
//Log
EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, NewLocale.Id, AyaType.Locale, AyaEvent.Created), ct);
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, NewLocale.Id, AyaType.Locale, AyaEvent.Created), ct);
return NewLocale;
}
@@ -113,12 +113,12 @@ namespace AyaNova.Biz
#if (DEBUG)
internal AyaNova.Api.Controllers.LocaleController.LocaleCoverageInfo LocaleKeyCoverage()
internal async Task<AyaNova.Api.Controllers.LocaleController.LocaleCoverageInfo> LocaleKeyCoverageAsync()
{
AyaNova.Api.Controllers.LocaleController.LocaleCoverageInfo L = new AyaNova.Api.Controllers.LocaleController.LocaleCoverageInfo();
L.RequestedKeys = ServerBootConfig.LocaleKeysRequested;
L.RequestedKeys.Sort();
var AllKeys = GetKeyList();
var AllKeys = await GetKeyListAsync();
foreach (string StockKey in AllKeys)
{
if (!L.RequestedKeys.Contains(StockKey))
@@ -171,9 +171,9 @@ namespace AyaNova.Biz
TrackRequestedKey(param);
#endif
AyContext ct = ServiceProviderProvider.DBContext;
if (!LocaleExistsStatic(localeId, ct))
if (!await LocaleExistsStaticAsync(localeId, ct))
localeId = ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE_ID;
var ret = await ct.LocaleItem.Where(x => x.LocaleId == localeId && param.Contains(x.Key)).ToDictionaryAsync(x => x.Key, x => x.Display);
var ret = await ct.LocaleItem.Where(x => x.LocaleId == localeId && param.Contains(x.Key)).AsNoTracking().ToDictionaryAsync(x => x.Key, x => x.Display);
return ret;
}
@@ -183,7 +183,7 @@ namespace AyaNova.Biz
{
if (ct == null)
ct = ServiceProviderProvider.DBContext;
var ret = await ct.Locale.Where(x => x.Id == localeId).Select(m => m.CjkIndex).SingleOrDefaultAsync();
var ret = await ct.Locale.Where(x => x.Id == localeId).AsNoTracking().Select(m => m.CjkIndex).SingleOrDefaultAsync();
return ret;
}
@@ -201,14 +201,14 @@ namespace AyaNova.Biz
TrackRequestedKey(key);
#endif
AyContext ct = ServiceProviderProvider.DBContext;
return await ct.LocaleItem.Where(m => m.LocaleId == ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE_ID && m.Key == key).Select(m => m.Display).FirstOrDefaultAsync();
return await ct.LocaleItem.Where(m => m.LocaleId == ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE_ID && m.Key == key).Select(m => m.Display).AsNoTracking().FirstOrDefaultAsync();
}
//Get all stock keys that are valid (used for import)
internal static List<string> GetKeyList()
internal static async Task<List<string>> GetKeyListAsync()
{
AyContext ct = ServiceProviderProvider.DBContext;
return ct.LocaleItem.Where(m => m.LocaleId == 1).OrderBy(m => m.Key).Select(m => m.Key).ToList();
return await ct.LocaleItem.Where(m => m.LocaleId == 1).OrderBy(m => m.Key).Select(m => m.Key).AsNoTracking().ToListAsync();
}
@@ -262,7 +262,7 @@ namespace AyaNova.Biz
//this will allow EF to check it out
ct.Entry(dbObj).OriginalValues["ConcurrencyToken"] = inObj.ConcurrencyToken;
ValidateAsync(dbObj.Name, false);
await ValidateAsync(dbObj.Name, false);
if (HasErrors)
return false;
@@ -281,13 +281,14 @@ namespace AyaNova.Biz
//DELETE
//
internal bool Delete(Locale dbObj)
internal async Task<bool> DeleteAsync(Locale dbObj)
{
//Determine if the object can be deleted, do the deletion tentatively
ValidateCanDeleteAsync(dbObj);
await ValidateCanDeleteAsync(dbObj);
if (HasErrors)
return false;
ct.Locale.Remove(dbObj);
await ct.SaveChangesAsync();
return true;
}
@@ -310,7 +311,7 @@ namespace AyaNova.Biz
AddError(ApiErrorCode.VALIDATION_LENGTH_EXCEEDED, "Name", "255 char max");
//Name must be unique
if( await ct.Locale.AnyAsync(m => m.Name == inObjName))
if (await ct.Locale.AnyAsync(m => m.Name == inObjName))
AddError(ApiErrorCode.VALIDATION_NOT_UNIQUE, "Name");
return;
@@ -348,51 +349,51 @@ namespace AyaNova.Biz
//UTILITIES
//
public long LocaleNameToId(string localeName)
public async Task<long> LocaleNameToIdAsync(string localeName)
{
var v = ct.Locale.Where(c => c.Name == localeName).Select(x => x.Id);
if (v.Count() < 1) return 0;
return v.First();
var v = await ct.Locale.AsNoTracking().FirstOrDefaultAsync(c => c.Name == localeName);
if (v == null) return 0;
return v.Id;
}
public static long LocaleNameToIdStatic(string localeName, AyContext ct = null)
public static async Task<long> LocaleNameToIdStaticAsync(string localeName, AyContext ct = null)
{
if (ct == null)
{
ct = ServiceProviderProvider.DBContext;
}
var v = ct.Locale.Where(c => c.Name == localeName).Select(x => x.Id);
if (v.Count() < 1) return ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE_ID;
return v.First();
var v = await ct.Locale.AsNoTracking().FirstOrDefaultAsync(c => c.Name == localeName);
if (v == null) return ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE_ID;
return v.Id;
}
public bool LocaleExists(string localeName)
public async Task<bool> LocaleExistsAsync(string localeName)
{
return LocaleNameToId(localeName) != 0;
return await LocaleNameToIdAsync(localeName) != 0;
}
public bool LocaleExists(long id)
public async Task<bool> LocaleExistsAsync(long id)
{
return ct.Locale.Any(e => e.Id == id);
return await ct.Locale.AnyAsync(e => e.Id == id);
}
public static bool LocaleExistsStatic(long id, AyContext ct)
public static async Task<bool> LocaleExistsStaticAsync(long id, AyContext ct)
{
return ct.Locale.Any(e => e.Id == id);
return await ct.Locale.AnyAsync(e => e.Id == id);
}
public static long EnsuredLocaleIdStatic(long id, AyContext ct)
public static async Task<long> EnsuredLocaleIdStaticAsync(long id, AyContext ct)
{
if (!ct.Locale.Any(e => e.Id == id))
if (!await ct.Locale.AnyAsync(e => e.Id == id))
return ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE_ID;
return id;
}
public bool LocaleItemExists(long id)
public async Task<bool> LocaleItemExistsAsync(long id)
{
return ct.LocaleItem.Any(e => e.Id == id);
return await ct.LocaleItem.AnyAsync(e => e.Id == id);
}
@@ -478,23 +479,23 @@ namespace AyaNova.Biz
/// Ensure stock locales and setup defaults
/// Called by boot preflight check code AFTER it has already ensured the locale is a two letter code if stock one was chosen
/// </summary>
public void ValidateLocales()
public async Task ValidateLocalesAsync()
{
//Ensure default locales are present and that there is a server default locale that exists
if (!LocaleExists("en"))
if (!await LocaleExistsAsync("en"))
{
throw new System.Exception($"E1015: stock locale English (en) not found in database!");
}
if (!LocaleExists("es"))
if (!await LocaleExistsAsync("es"))
{
throw new System.Exception($"E1015: stock locale Spanish (es) not found in database!");
}
if (!LocaleExists("de"))
if (!await LocaleExistsAsync("de"))
{
throw new System.Exception($"E1015: stock locale German (de) not found in database!");
}
if (!LocaleExists("fr"))
if (!await LocaleExistsAsync("fr"))
{
throw new System.Exception($"E1015: stock locale French (fr) not found in database!");
}
@@ -508,7 +509,7 @@ namespace AyaNova.Biz
case "fr":
break;
default:
if (!LocaleExists(ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE))
if (!await LocaleExistsAsync(ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE))
{
throw new System.Exception($"E1015: stock locale {ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE} not found in database!");
}
@@ -517,14 +518,16 @@ namespace AyaNova.Biz
}
//Put the default locale ID number into the ServerBootConfig for later use
ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE_ID = LocaleNameToId(ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE);
ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE_ID = await LocaleNameToIdAsync(ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE);
}
/////////////////////////////////////////////////////////////////////
/// IMPORT v7 implementation
public async Task<bool> ImportV7Async(JObject j, List<ImportAyaNova7MapItem> importMap, Guid jobId, Dictionary<string, Dictionary<Guid, string>> tagLists)
public async Task<bool> ImportV7Async(
JObject j, List<ImportAyaNova7MapItem> importMap,
Guid jobId, Dictionary<string, Dictionary<Guid, string>> tagLists)
{
//some types need to import from more than one source hence the seemingly redundant switch statement for futureproofing
switch (j["IMPORT_TASK"].Value<string>())
@@ -538,7 +541,7 @@ namespace AyaNova.Biz
var SourceLocaleName = v.Groups[1].ToString();
//Ensure doesn't already exist
if (LocaleExists(SourceLocaleName))
if (await LocaleExistsAsync(SourceLocaleName))
{
//If there are any validation errors, log in joblog and move on
JobsBiz.LogJob(jobId, $"LocaleBiz::ImportV7Async -> - Locale \"{SourceLocaleName}\" already exists in database, can not import over an existing locale", ct);
@@ -552,7 +555,7 @@ namespace AyaNova.Biz
SkipKeys.Add("V7_TYPE");
SkipKeys.Add("IMPORT_TASK");
List<string> ValidKeys = GetKeyList();
List<string> ValidKeys = await GetKeyListAsync();
Dictionary<string, string> NewLocaleDict = new Dictionary<string, string>();
foreach (var Pair in j.Children())
{
@@ -587,7 +590,7 @@ namespace AyaNova.Biz
{
if (!NewLocaleDict.ContainsKey(s))
{
NewLocaleDict.Add(s, GetDefaultLocalizedTextAsync(s).Result);
NewLocaleDict.Add(s, await GetDefaultLocalizedTextAsync(s));
}
}
@@ -607,18 +610,18 @@ namespace AyaNova.Biz
l.LocaleItems.Add(new LocaleItem() { Key = K.Key, Display = K.Value });
}
ct.Locale.Add(l);
ct.SaveChanges();
await ct.Locale.AddAsync(l);
await ct.SaveChangesAsync();
//Log now that we have the Id, note that there is no source created / modified for this so just attributing to current userId
EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, l.Id, AyaType.Locale, AyaEvent.Created), ct);
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, l.Id, AyaType.Locale, AyaEvent.Created), ct);
}
break;
}
//just to hide compiler warning for now
await Task.CompletedTask;
//this is the equivalent of returning void for a Task signature with nothing to return
return true;
}

View File

@@ -61,7 +61,7 @@ namespace AyaNova.Biz
//Ensure locales are present, not missing any keys and that there is a server default locale that exists
LocaleBiz lb = LocaleBiz.GetBizInternal(ServiceProviderProvider.DBContext, 1, AuthorizationRoles.OpsAdminFull);
lb.ValidateLocales();
lb.ValidateLocalesAsync();
}

View File

@@ -125,7 +125,7 @@ namespace AyaNova.Biz
searchParameters.Phrase = searchParameters.Phrase.Replace("*", "%");
//BREAK SEARCH PHRASE INTO SEPARATE TERMS
var PhraseItems = BreakSearchPhrase(localeId, searchParameters.Phrase);
var PhraseItems = await BreakSearchPhraseAsync(localeId, searchParameters.Phrase);
//SPLIT OUT WILDCARDS FROM NON WILDCARDS
List<string> WildCardSearchTerms = new List<string>();
@@ -481,10 +481,10 @@ namespace AyaNova.Biz
}
//BREAK OBJECT TEXT STRINGS INTO KEYWORD LIST
List<string> KeyWordList = Break(p.LocaleId, p.Words);
List<string> KeyWordList = await BreakAsync(p.LocaleId, p.Words);
//BREAK NAME STRING
List<string> NameKeyWordList = Break(p.LocaleId, p.Name);
List<string> NameKeyWordList = await BreakAsync(p.LocaleId, p.Name);
//EARLY EXIT IF NO KEYWORDS OR NAME RECORD OR TAGS TO PROCESS
@@ -706,7 +706,7 @@ cache or provide directly the locale to save time repeatedly fetching it when do
//Get the current stopwords for the user's locale
//called in here in this class and also by any bulk ops like seeding etc
internal static LocaleWordBreakingData GetLocaleSearchData(long localeId, AyContext ct = null)
internal static async Task<LocaleWordBreakingData> GetLocaleSearchDataAsync(long localeId, AyContext ct = null)
{
LocaleWordBreakingData LSD = new LocaleWordBreakingData();
if (ct == null)
@@ -714,7 +714,7 @@ cache or provide directly the locale to save time repeatedly fetching it when do
//Get stopwords
//Validate locale id, if not right then use default instead
var Param = new List<string>();
localeId = LocaleBiz.EnsuredLocaleIdStatic(localeId, ct);
localeId = await LocaleBiz.EnsuredLocaleIdStaticAsync(localeId, ct);
Param.Add("StopWords1");
Param.Add("StopWords2");
Param.Add("StopWords3");
@@ -722,7 +722,7 @@ cache or provide directly the locale to save time repeatedly fetching it when do
Param.Add("StopWords5");
Param.Add("StopWords6");
Param.Add("StopWords7");
var Stops = LocaleBiz.GetSubsetStaticAsync(Param, localeId).Result;
var Stops = await LocaleBiz.GetSubsetStaticAsync(Param, localeId);
foreach (KeyValuePair<string, string> kvp in Stops)
{
@@ -733,7 +733,7 @@ cache or provide directly the locale to save time repeatedly fetching it when do
}
}
LSD.CJKIndex = LocaleBiz.GetCJKIndexAsync(localeId, ct).Result;
LSD.CJKIndex = await LocaleBiz.GetCJKIndexAsync(localeId, ct);
return LSD;
}
@@ -751,30 +751,30 @@ cache or provide directly the locale to save time repeatedly fetching it when do
/// (languages with no easily identifiable word boundaries as in english)
/// </summary>
/// <returns>List of strings</returns>
internal static List<string> Break(long localeId, List<string> textStrings)
internal static async Task<List<string>> BreakAsync(long localeId, List<string> textStrings)
{
return BreakCore(localeId, false, textStrings);
return await BreakCoreAsync(localeId, false, textStrings);
}
/// <summary>
///
/// </summary>
internal static List<string> Break(long localeId, string textString)
internal static async Task<List<string>> BreakAsync(long localeId, string textString)
{
List<string> textStrings = new List<string>(1);
textStrings.Add(textString);
return BreakCore(localeId, false, textStrings);
return await BreakCoreAsync(localeId, false, textStrings);
}
/// <summary>
/// Used to Process users search phrase and preserve wild
/// cards entered
/// </summary>
internal static List<string> BreakSearchPhrase(long localeId, string searchPhrase)
internal static async Task<List<string>> BreakSearchPhraseAsync(long localeId, string searchPhrase)
{
List<string> textStrings = new List<string>();
textStrings.Add(searchPhrase);
return BreakCore(localeId, true, textStrings);
return await BreakCoreAsync(localeId, true, textStrings);
}
/// <summary>
@@ -790,14 +790,14 @@ cache or provide directly the locale to save time repeatedly fetching it when do
localeWordBreakingDataCache.Remove(localeId);
}
internal static List<string> BreakCore(long localeId, bool KeepWildCards, List<string> textStrings)
internal static async Task<List<string>> BreakCoreAsync(long localeId, bool KeepWildCards, List<string> textStrings)
{
//For stopwords and CJKIndex flag value
//if not provided (will be provided by seeder for performance but normally never) then fetch
if (!localeWordBreakingDataCache.ContainsKey(localeId))
{
localeWordBreakingDataCache.Add(localeId, GetLocaleSearchData(localeId));
localeWordBreakingDataCache.Add(localeId, await GetLocaleSearchDataAsync(localeId));
}
var localeWordBreakData = localeWordBreakingDataCache[localeId];

View File

@@ -32,12 +32,11 @@ namespace AyaNova.Biz
}
//This is where active tech license consumers are accounted for
internal static long ActiveCount
internal static async Task<long> ActiveCount()
{
get
{
return ServiceProviderProvider.DBContext.User.Where(x => x.Active == true && (x.UserType == UserType.Schedulable || x.UserType == UserType.Subcontractor)).LongCount();
}
var ct = ServiceProviderProvider.DBContext;
var ret = await ct.User.Where(x => x.Active == true && (x.UserType == UserType.Schedulable || x.UserType == UserType.Subcontractor)).LongCountAsync();
return ret;
}
internal static UserBiz GetBiz(AyContext ct, Microsoft.AspNetCore.Http.HttpContext httpContext)
@@ -830,7 +829,7 @@ namespace AyaNova.Biz
break;
case "eventlog":
{
ImportAyaNova7Biz.LogEventCreatedModifiedEvents(j, importMap, BizType, ct);
ImportAyaNova7Biz.LogEventCreatedModifiedEventsAsync(j, importMap, BizType, ct);
}
break;
case "locale":
@@ -885,7 +884,7 @@ namespace AyaNova.Biz
break;
}
u.LocaleId = LocaleBiz.LocaleNameToIdStatic(NewLocaleName, ct);
u.LocaleId = LocaleBiz.LocaleNameToIdStaticAsync(NewLocaleName, ct);
ct.SaveChanges();
#endregion set locale

View File

@@ -469,9 +469,9 @@ namespace AyaNova.Util
GenSeedUser(log, 1, AuthorizationRoles.OpsAdminLimited, UserType.NonSchedulable, timeZoneOffset, false, "TEST_INACTIVE", "TEST_INACTIVE");
//Alternate locale users for each stock locale
GenSeedUser(log, 1, AuthorizationRoles.All, UserType.Administrator, timeZoneOffset, true, "de", "de", LocaleBiz.LocaleNameToIdStatic("de"));
GenSeedUser(log, 1, AuthorizationRoles.All, UserType.Administrator, timeZoneOffset, true, "es", "es", LocaleBiz.LocaleNameToIdStatic("es"));
GenSeedUser(log, 1, AuthorizationRoles.All, UserType.Administrator, timeZoneOffset, true, "fr", "fr", LocaleBiz.LocaleNameToIdStatic("fr"));
GenSeedUser(log, 1, AuthorizationRoles.All, UserType.Administrator, timeZoneOffset, true, "de", "de", LocaleBiz.LocaleNameToIdStaticAsync("de"));
GenSeedUser(log, 1, AuthorizationRoles.All, UserType.Administrator, timeZoneOffset, true, "es", "es", LocaleBiz.LocaleNameToIdStaticAsync("es"));
GenSeedUser(log, 1, AuthorizationRoles.All, UserType.Administrator, timeZoneOffset, true, "fr", "fr", LocaleBiz.LocaleNameToIdStaticAsync("fr"));
}