//public IEnumerable<DB_Word> Words => DB_Elements
        //    .Where(dbElement => dbElement.ElementType.Equals(FlexData.ElementType.DB_Word))
        //    .Cast<DB_WordElement>();

        //public Task<WordElementBuilder> LoadWordAsync(int wordBuilder_ID) => Task.Run(() => LoadWord(wordBuilder_ID));

        //public Task<IQueryable<WordElementBuilder>> LoadAllWordsAsync() => Task.Run(() => LoadAllWords());

        public Task SaveWordAsync(DB_Word dbWord, DB_WeightedWord defaultWeightedWord, IEnumerable <DB_WeightedWord> alternateWeightedWords) => Task.Run(() =>
        {
            //using (TransactionScope transaction = new TransactionScope())
            //{
            //    SaveWord(dbWord, defaultWeightedWord, alternateWeightedWords);
            //}
            //OnWordChanged(dbWord.ID);
        });
        //private IQueryable<WordElementBuilder> LoadAllWords() => DB_Elements
        //    .Where(dbElement => dbElement.ElementType.Equals(FlexData.ElementType.DB_Word))
        //    .Select(dbBuilder => LoadWord(dbBuilder.ID));

        //private WordElementBuilder LoadWord(int wordBuilder_ID)
        //{
        //    WordElementBuilder wordBuilder;
        //    DB_Word dbWord = DB_Words.Single(element => element.ID.Equals(wordBuilder_ID));
        //    wordBuilder = FlexData.Word.BuilderOfType((FlexData.WordType)dbWord.WordType);
        //    wordBuilder.FlexDB_ID = wordBuilder_ID;
        //    LoadWordLayersOf(wordBuilder);
        //    Task.Run(() =>
        //    {
        //        WeightedWord defaultWeightedWord = DB_WeightedWords
        //            .Where(dbWeightedWord => dbWeightedWord.WordElement.Equals(wordBuilder_ID) && dbWord.DefaultWeightedWord.Equals(dbWeightedWord.ID))
        //            .Select(dbWeightedWord => new WeightedWord(dbWeightedWord.Text, dbWeightedWord.Weight))
        //            .Single();
        //        IEnumerable<WeightedWord> alternates = DB_WeightedWords
        //            .Where(dbWeightedWord => dbWeightedWord.WordElement.Equals(wordBuilder_ID) && !dbWord.DefaultWeightedWord.Equals(dbWeightedWord.ID))
        //            .Select(dbWeightedWord => new WeightedWord(dbWeightedWord.Text, dbWeightedWord.Weight));
        //        if (alternates.Count().Equals(0))
        //            wordBuilder.WordSource = new SingleWordSource(defaultWeightedWord.Text);
        //        else
        //            wordBuilder.WordSource = new WordSelector(defaultWeightedWord, alternates);
        //    });
        //    return wordBuilder;
        //}

        //private void LoadWordLayersOf(WordElementBuilder wordBuilder)
        //{
        //    LayerWord wordLayer = LayerWords.Single(wordLayer => wordLayer.ID.Equals(wordBuilder.FlexDB_ID));
        //    wordBuilder.ExpletiveSubjectSpecified = wordLayer.ExpletiveSubject != null;
        //    if (wordBuilder.ExpletiveSubjectSpecified) wordBuilder.ExpletiveSubject = (bool)wordLayer.ExpletiveSubject;
        //    wordBuilder.ProperSpecified = wordLayer.Proper != null;
        //    if (wordBuilder.ProperSpecified) wordBuilder.Proper = (bool)wordLayer.Proper;
        //    wordBuilder.InflectionSpecified = wordLayer.Inflection != null;
        //    if (wordBuilder.InflectionSpecified) wordBuilder.Inflection = (inflection)wordLayer.Inflection;
        //    wordBuilder.CannedSpecified = wordLayer.Canned != null;
        //    if (wordBuilder.CannedSpecified) wordBuilder.Canned = (bool)wordLayer.Canned;
        //    switch (wordBuilder)
        //    {
        //        case PronounBuilder pronounBuilder:
        //            LoadPronounLayerOf(pronounBuilder);
        //            break;
        //    }
        //}

        //private void LoadPronounLayerOf(PronounBuilder pronounBuilder)
        //{
        //    LayerPronoun pronounLayer = LayerPronouns.Single(pronounLayer => pronounLayer.ID.Equals(pronounBuilder.FlexDB_ID));
        //    pronounBuilder.CaseSpecified = pronounLayer.PronounCase != null;
        //    if (pronounBuilder.CaseSpecified) pronounBuilder.Case = (PronounCase)pronounLayer.PronounCase;
        //    pronounBuilder.PersonSpecified = pronounLayer.Person != null;
        //    if (pronounBuilder.PersonSpecified) pronounBuilder.Person = (person)pronounLayer.Person;
        //    pronounBuilder.NumberSpecified = pronounLayer.Number != null;
        //    if (pronounBuilder.NumberSpecified) pronounBuilder.Number = (numberAgreement)pronounLayer.Number;
        //    pronounBuilder.GenderSpecified = pronounLayer.Gender != null;
        //    if (pronounBuilder.GenderSpecified) pronounBuilder.Gender = (gender)pronounLayer.Gender;
        //}

        private void SaveWord(WordElementBuilder wordBuilder)
        {
            DB_Element dbSavedElement;
            bool       isNewDB_Element = wordBuilder.FlexDB_ID == 0;

            // If the word doesn't support variations, and we've already saved a matching DB_Word in the database, don't save another one
            if (!wordBuilder.SupportsVariations)
            {
                DB_Word existingDB_WordThatMatches = DB_Words
                                                     .Where(dbWord => dbWord.WordType.Equals(FlexData.Word.TypeOf(wordBuilder)))
                                                     .FirstOrDefault(wordElement => wordElement.DefaultForm.Equals(wordBuilder.WordSource.DefaultWord));
                if (existingDB_WordThatMatches != null)
                {
                    wordBuilder.FlexDB_ID = existingDB_WordThatMatches.ID;
                    return;
                }
            }
            // Make sure we have a WordElementBuilder with a valid FlexDB_ID.
            // We'll need that FlexDB_ID so DB_WeightedWords can refer to it when we save them in the database.
            if (isNewDB_Element)        // The word builder does not already exist in the database.  We need to insert it so it has an ID.
            {
                dbSavedElement            = new DB_Element(FlexData.ElementType.DB_Word);
                dbSavedElement.FormsCount = wordBuilder.CountForms();
                DB_Elements.InsertOnSubmit(dbSavedElement);
                SubmitChanges();
                // Now we have the ID available from the database.  Assign the ID to the in-memory object, so we'll remember it's not new if we update it
                wordBuilder.FlexDB_ID = dbSavedElement.ID;
            }
            else  // The word builder already exists in the database
            {
                dbSavedElement            = DB_Elements.Single(dbElement => dbElement.ID.Equals(wordBuilder.FlexDB_ID));
                dbSavedElement.FormsCount = wordBuilder.CountForms();
            }
            UpdateWordLayersFor(wordBuilder);
            SubmitChanges();
            OnWordChanged(wordBuilder.FlexDB_ID);
        }