private void UpdateWordLayersFor(WordElementBuilder wordBuilder) { LayerWord dbSavedWordLayer; bool isNewLayerWord; LayerWord existingWordLayer = LayerWords.FirstOrDefault(wordLayer => wordLayer.ID.Equals(wordBuilder.FlexDB_ID)); if (existingWordLayer != null) { isNewLayerWord = false; dbSavedWordLayer = existingWordLayer; } else { isNewLayerWord = true; dbSavedWordLayer = new LayerWord(wordBuilder.FlexDB_ID, FlexData.Word.TypeOf(wordBuilder)); LayerWords.InsertOnSubmit(dbSavedWordLayer); } dbSavedWordLayer.ExpletiveSubject = wordBuilder.ExpletiveSubjectSpecified ? wordBuilder.ExpletiveSubject : null; dbSavedWordLayer.Proper = wordBuilder.ProperSpecified ? wordBuilder.Proper : null; dbSavedWordLayer.Inflection = wordBuilder.InflectionSpecified ? (byte)wordBuilder.Inflection : null; dbSavedWordLayer.Canned = wordBuilder.CannedSpecified ? wordBuilder.Canned : null; UpdateWeightedWordsFor(wordBuilder, dbSavedWordLayer, isNewLayerWord); UpdateLayerWord(dbSavedWordLayer); switch (wordBuilder) { case PronounBuilder pronoun: UpdatePronounLayerFor(pronoun); break; default: break; } }
private void UpdateWeightedWordsFor(WordElementBuilder wordBuilder, LayerWord wordLayer, bool isNewLayerWord) { // The DB_WeightedWords that are already in the database belonging to this word IEnumerable <DB_WeightedWord> existingWeightedWordsForThisBuilder = DB_WeightedWords .Where(dbWeightedWord => dbWeightedWord.WordElement.Equals(wordBuilder.FlexDB_ID)); switch (wordBuilder.WordSource) { case SingleWordSource sws: // If a WordElementBuilder has only a single word form, then in-memory its WordSource is a SingleWordSource. DB_WeightedWord existingDefaultWeightedWord = existingWeightedWordsForThisBuilder .FirstOrDefault(dbWeightedWord => dbWeightedWord.Text.Equals(sws.GetWord())); DB_WeightedWord dbSavedDefaultWeightedWord; if (existingDefaultWeightedWord == null) { dbSavedDefaultWeightedWord = new DB_WeightedWord { WordElement = wordBuilder.FlexDB_ID, Text = sws.GetWord() }; DB_WeightedWords.InsertOnSubmit(dbSavedDefaultWeightedWord); SubmitChanges(); } else { dbSavedDefaultWeightedWord = existingDefaultWeightedWord; dbSavedDefaultWeightedWord.Text = sws.GetWord(); UpdateDB_WeightedWord(dbSavedDefaultWeightedWord); } wordLayer.DefaultWeightedWord = dbSavedDefaultWeightedWord.ID; DB_WeightedWords.DeleteAllOnSubmit(existingWeightedWordsForThisBuilder .Where(dbWeightedWord => dbWeightedWord != dbSavedDefaultWeightedWord)); break; case WordSelector ws: if (isNewLayerWord) { DB_WeightedWords.InsertAllOnSubmit(ws.GetWeightedWordVariations() .Select(wsVariation => new DB_WeightedWord { WordElement = wordBuilder.FlexDB_ID, Text = wsVariation.Text, Weight = wsVariation.Weight })); SubmitChanges(); // Now that the newly inserted DB_WeightedWords have their IDs assigned, we can figure out which ID to make the Builder's DefaultForm. // If a WordElementBuilder has multiple word forms, then in-memory its WordSource is a WordSelector. // In this case we store it to the database as a collection of DB_WeightedWord that refer to the DB_WordBuilder, and the DB_WordBuilder // has a reference to ONE of those. The DB_WordBuilder has its SingleWord set to null because it has multiple word forms. wordLayer.DefaultWeightedWord = DB_WeightedWords .Single(dbWeightedWord => dbWeightedWord.WordElement.Equals(wordBuilder.FlexDB_ID) && dbWeightedWord.Text.Equals(ws.Default.Text)) .ID; } else // We're updating a DB_WordBuilder that's already in the database { DB_WeightedWords.DeleteAllOnSubmit(existingWeightedWordsForThisBuilder .Where(dbWeightedWord => !ws.GetWeightedWordVariations().Any(variation => variation.Text.Equals(dbWeightedWord.Text)))); IEnumerable <DB_WeightedWord> existingWeightedWordsToUpdate = existingWeightedWordsForThisBuilder .Join(ws.GetWeightedWordVariations(), existingDBWeightedWord => existingDBWeightedWord.Text, wsVariation => wsVariation.Text, (existingDBWeightedWord, wsVariation) => existingDBWeightedWord) .Where(existingDBWeightedWord => existingDBWeightedWord.Weight != ws.WeightOf(existingDBWeightedWord.Text)); // Update weights for existing DB_WeightedWords, in case the user changed them in the UI foreach (DB_WeightedWord eachWeightedWordToUpdate in existingWeightedWordsToUpdate) { eachWeightedWordToUpdate.Weight = ws.GetWeightedWordVariations() .Single(wsVariation => wsVariation.Text.Equals(eachWeightedWordToUpdate.Text)) .Weight; } // New DB_WeightedWords corresponding to words that are NOT already in the database, but ARE present in the WordSelector that we're saving IEnumerable <DB_WeightedWord> newWeightedWordsToInsert = ws.GetWeightedWordVariations() .Where(wsVariation => !existingWeightedWordsForThisBuilder.Any(dbWeightedWord => dbWeightedWord.Text.Equals(wsVariation.Text))) .Select(wsVariation => new DB_WeightedWord { WordElement = wordBuilder.FlexDB_ID, Text = wsVariation.Text, Weight = wsVariation.Weight }); DB_WeightedWords.InsertAllOnSubmit(newWeightedWordsToInsert); SubmitChanges(); // After doing this, we have valid IDs for the DB_WeightedWords // Now update the DB_WordBuilder. Since the in-memory WordElementBuilder has a WordSelector as its WordSource, the database form needs // to have DefaultForm set, and SingleWord NOT set. wordLayer.DefaultWeightedWord = existingWeightedWordsForThisBuilder.Concat(newWeightedWordsToInsert) .Single(dbWeightedWord => dbWeightedWord.WordElement == wordBuilder.FlexDB_ID && dbWeightedWord.Text.Equals(ws.Default.Text)) .ID; } break; default: break; } }