From 0d52c331e7482883dfe8051c7368664aed6a26ed Mon Sep 17 00:00:00 2001 From: John Cardinal Date: Thu, 11 Oct 2018 17:57:02 +0000 Subject: [PATCH] --- server/AyaNova/biz/Search.cs | 102 ++++++++--------------------------- 1 file changed, 21 insertions(+), 81 deletions(-) diff --git a/server/AyaNova/biz/Search.cs b/server/AyaNova/biz/Search.cs index 281c75a4..17c5243f 100644 --- a/server/AyaNova/biz/Search.cs +++ b/server/AyaNova/biz/Search.cs @@ -401,7 +401,7 @@ namespace AyaNova.Biz private static void ProcessKeywords(long localeId, long objectID, AyaType objectType, bool newRecord, string name, params string[] text) { - AyContext ct = ServiceProviderProvider.DBContext; + //AyContext ct = ServiceProviderProvider.DBContext; #if (DEBUG) if (objectType == AyaType.TagMap || objectType == AyaType.JobOperations || objectType == AyaType.Locale) { @@ -433,7 +433,7 @@ namespace AyaNova.Biz List MatchingKeywordIdList = new List(); //ITERATE ALL THE KEYWORDS, SEARCH IN THE SEARCHDICTIONARY TABLE AND COLLECT ID'S OF ANY PRE-EXISTING IN DB KEYWORDS - var ExistingKeywordMatches = ct.SearchDictionary.AsNoTracking().Where(m => KeyWordList.Contains(m.Word)).ToDictionary(m => m.Id, m => m.Word); + var ExistingKeywordMatches = ServiceProviderProvider.DBContext.SearchDictionary.AsNoTracking().Where(m => KeyWordList.Contains(m.Word)).ToDictionary(m => m.Id, m => m.Word); //Put the matching keyword ID's into the list foreach (KeyValuePair K in ExistingKeywordMatches) { @@ -446,11 +446,10 @@ namespace AyaNova.Biz //-------- START CRITICAL SECTION ----------- //------------------------------------------- #region NEW WORD ADDITION second attempt, do it word by word and accept clashes and handle them - +#if (DEBUG) var log = AyaNova.Util.ApplicationLogging.CreateLogger("### Search::ProcessKeywords ###"); +#endif - // using (var transaction = ct.Database.BeginTransaction()) - //{ foreach (string KeyWord in KeyWordList) { if (!ExistingKeywordMatches.ContainsValue(KeyWord)) @@ -464,25 +463,30 @@ namespace AyaNova.Biz try { //ADD WORD TO DICTIONARY, SAVE THE ID INTO THE MATCHINGKEYWORDIDLIST - ct.SearchDictionary.Add(NewWord); - ct.SaveChanges(); + var CtAdd = ServiceProviderProvider.DBContext; + CtAdd.SearchDictionary.Add(NewWord); + CtAdd.SaveChanges(); MatchingKeywordIdList.Add(new MatchingDictionaryEntry() { DictionaryId = NewWord.Id, InName = NameKeyWordList.Contains(KeyWord) }); //It exists now ExistingKeywordMatches.Add(NewWord.Id, NewWord.Word); } catch (Microsoft.EntityFrameworkCore.DbUpdateException ex) { +#if (DEBUG) log.LogInformation($"###################### Exception caught attempting to add word: '{KeyWord}' fetching instead..."); +#endif //FAIL DUE TO OTHER CAUSE THAN WORD ALREADY ADDED? if (ex.InnerException == null || !ex.InnerException.Message.Contains("asearchdictionary_word_idx")) { +#if (DEBUG) log.LogInformation($"###################### Unexpected inner exception on add word: '{KeyWord}'!?"); +#endif throw ex; } //FETCH THE WORD ID, PLACE IN MATCHINGKEYWORDLIST AND MOVE ON TO THE NEXT WORD //LOOKAT: 2018-10-10 15:34:34.0587|ERROR|Server Exception|Error=>System.InvalidOperationException: Sequence contains no elements - var SearchDictionaryMatchFoundInDB = ct.SearchDictionary.AsNoTracking().Where(x => x.Word == KeyWord).FirstOrDefault(); + var SearchDictionaryMatchFoundInDB = ServiceProviderProvider.DBContext.SearchDictionary.AsNoTracking().Where(x => x.Word == KeyWord).FirstOrDefault(); if (SearchDictionaryMatchFoundInDB != null) { MatchingKeywordIdList.Add(new MatchingDictionaryEntry() { DictionaryId = SearchDictionaryMatchFoundInDB.Id, InName = NameKeyWordList.Contains(KeyWord) }); @@ -491,88 +495,23 @@ namespace AyaNova.Biz } else { +#if (DEBUG) log.LogInformation($"###################### NULL when expected to find word: '{KeyWord}'!?"); +#endif } } catch (Exception ex) { +#if (DEBUG) log.LogInformation(ex, $"###################### Unexpected exception adding word: '{KeyWord}'!?"); - +#endif + throw ex; } } } - // transaction.Commit(); - //} + #endregion second attempt - #region NEW WORD ADDITION: First naive attempt, clashing too much - - // //ITERATE THROUGH THE KEYWORDS THAT DO *NOT* HAVE MATCHES IN THE SEARCHDICTIONARY AND ADD THEM TO THE SEARCH DICTIONARY, COLLECTING THEIR ID'S - // bool NewWordsAdded = false; - // var NewSearchDictionaryWordsList = new List(); - // foreach (string KeyWord in KeyWordList) - // { - // if (!ExistingKeywordMatches.ContainsValue(KeyWord)) - // { - // NewSearchDictionaryWordsList.Add(new SearchDictionary() { Word = KeyWord }); - // NewWordsAdded = true; - // } - // } - - // //Save the context in order to get the id's of the new words added - // if (NewWordsAdded) - // { - // //adding in a range sped this up noticeably - // ct.SearchDictionary.AddRange(NewSearchDictionaryWordsList); - // try - // { - // ct.SaveChanges(); - // } - // catch (Exception ex) - // { - // //In integration testing hit duplicate values of widget names - // //adjusted uniquify code in test util class to use milliseconds instead of seconds (duh) and didn't hit this again, - // //however just in case I'm leaving it here as a potential debug break point if it arises again - // //Outside of a test situation I can't imagine this will be an issue in actual production use - // //as it seems unlikely that two separate manual users inputting data are going to generate the same word at the same exact moment - // //in time - - // //This is actually quite frequent and needs to be fixed, it can happen from widget or taggroup etc, need to handle this scenario far better - // //Rather than locking, maybe try a repeat method instead with a timeout - - // /* - // 2018-10-10 02:48:38.2715|ERROR|Server Exception|Error=>Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details. - // ---> Npgsql.PostgresException: 23505: duplicate key value violates unique constraint "asearchdictionary_word_idx" - // */ - // throw ex; - // } - // } - - - // //Now add the id's of the newly created words to the matching keyword id list for this object - - // foreach (SearchDictionary SD in ct.SearchDictionary.Local) - // { - // bool IsName = false; - // if (NameKeyWordList.Contains(SD.Word)) - // IsName = true; - // //See if it's already in the matching keywordlist or needs to be added - // var ExistingMatch = MatchingKeywordIdList.Where(x => x.DictionaryId == SD.Id).FirstOrDefault(); - - // if (ExistingMatch == null)//If null then needs to be added - // MatchingKeywordIdList.Add(new MatchingDictionaryEntry() { DictionaryId = SD.Id, InName = IsName }); - // else - // { - // //Not null, but may need to be updated to reflect that it's in the name - // if (!ExistingMatch.InName && IsName) - // { - // ExistingMatch.InName = true; - // } - // } - // } - - #endregion first naive attempt - //-------- END CRITICAL SECTION ------------- //------------------------------------------- @@ -584,8 +523,9 @@ namespace AyaNova.Biz { NewSearchKeyList.Add(new SearchKey() { WordId = E.DictionaryId, InName = E.InName, ObjectId = objectID, ObjectType = objectType }); } - ct.SearchKey.AddRange(NewSearchKeyList); - ct.SaveChanges(); + var CtSearchKeyAdd = ServiceProviderProvider.DBContext; + CtSearchKeyAdd.SearchKey.AddRange(NewSearchKeyList); + CtSearchKeyAdd.SaveChanges(); //---------------------------------