public async Task CREATE_NEW()
        {
            PhraseEdit newPhraseEdit = null;

            var isAsyncComplete = false;
            var hasError        = false;

            EnqueueConditional(() => isAsyncComplete);
            await Setup();

            try
            {
                newPhraseEdit = await PhraseEdit.NewPhraseEditAsync();
            }
            catch
            {
                hasError = true;
            }
            finally
            {
                EnqueueCallback(
                    () => Assert.IsFalse(hasError),
                    () => Assert.IsNotNull(newPhraseEdit),
                    () => Assert.AreEqual(SeedData.Ton.EnglishId, newPhraseEdit.LanguageId),
                    () => Assert.IsNotNull(newPhraseEdit.Language)
                    );

                EnqueueTestComplete();
                Teardown();
                isAsyncComplete = true;
            }
        }
        public async Task MAKE_PHRASE_WITH_REALLY_LONG_VARIED_TEXT()
        {
            #region var reallyLongText
            var reallyLongText = @"asd;flkjghweqrey8iuweqpoiuqtw[eoizsdfslknjvzxcknvl;/,asdmf;lkasdfj asldkf a/sldkf jwoieuofvahsdkj;fa;weio:KJSLDJIOWEJLKSJDFLWIUQOWUQ}R|)(_)(*+_)(*&^%$#@!~~!@#$%^&*()_+|}{POIUYTREWQASDFGHJKL:			ZXCVBNM<>? "" wijwfekjsdkfj sdfj zxcvbnm,./';lljhgfdsqwertyuiop[]\=-0987654321`asd;flkjghweqrey8iuweqpoiuqtw[eoizsdfslknjvzxcknvl;/,asdmf;lkasdfj asldkf a/sldkf jwoieuofvahsdkj;fa;weio:KJSLDJIOWEJLKSJDFLWIUQOWUQ}R|)(_)(*+_)(*&^%$#@!~~!@#$%^&*()_+|}{POIUYTREWQASDFGHJKL:			ZXCVBNM<>? "" wijwfekjsdkfj sdfj zxcvbnm,./';lljhgfdsqwertyuiop[]\=-0987654321`asd;flkjghweqrey8iuweqpoiuqtw[eoizsdfslknjvzxcknvl;/,asdmf;lkasdfj asldkf a/sldkf jwoieuofvahsdkj;fa;weio:KJSLDJIOWEJLKSJDFLWIUQOWUQ}R|)(_)(*+_)(*&^%$#@!~~!@#$%^&*()_+|}{POIUYTREWQASDFGHJKL:			ZXCVBNM<>? "" wijwfekjsdkfj sdfj zxcvbnm,./';lljhgfdsqwertyuiop[]\=-0987654321`asd;flkjghweqrey8iuweqpoiuqtw[eoizsdfslknjvzxcknvl;/,asdmf;lkasdfj asldkf a/sldkf jwoieuofvahsdkj;fa;weio:KJSLDJIOWEJLKSJDFLWIUQOWUQ}R|)(_)(*+_)(*&^%$#@!~~!@#$%^&*()_+|}{POIUYTREWQASDFGHJKL:			ZXCVBNM<>? "" wijwfekjsdkfj sdfj zxcvbnm,./';lljhgfdsqwertyuiop[]\=-0987654321`asd;flkjghweqrey8iuweqpoiuqtw[eoizsdfslknjvzxcknvl;/,asdmf;lkasdfj asldkf a/sldkf jwoieuofvahsdkj;fa;weio:KJSLDJIOWEJLKSJDFLWIUQOWUQ}R|)(_)(*+_)(*&^%$#@!~~!@#$%^&*()_+|}{POIUYTREWQASDFGHJKL:			ZXCVBNM<>? "" wijwfekjsdkfj sdfj zxcvbnm,./';lljhgfdsqwertyuiop[]\=-0987654321`asd;flkjghweqrey8iuweqpoiuqtw[eoizsdfslknjvzxcknvl;/,asdmf;lkasdfj asldkf a/sldkf jwoieuofvahsdkj;fa;weio:KJSLDJIOWEJLKSJDFLWIUQOWUQ}R|)(_)(*+_)(*&^%$#@!~~!@#$%^&*()_+|}{POIUYTREWQASDFGHJKL:			ZXCVBNM<>? "" wijwfekjsdkfj sdfj zxcvbnm,./';lljhgfdsqwertyuiop[]\=-0987654321`asd;flkjghweqrey8iuweqpoiuqtw[eoizsdfslknjvzxcknvl;/,asdmf;lkasdfj asldkf a/sldkf jwoieuofvahsdkj;fa;weio:KJSLDJIOWEJLKSJDFLWIUQOWUQ}R|)(_)(*+_)(*&^%$#@!~~!@#$%^&*()_+|}{POIUYTREWQASDFGHJKL:			ZXCVBNM<>? "" wijwfekjsdkfj sdfj zxcvbnm,./';lljhgfdsqwertyuiop[]\=-0987654321`asd;flkjghweqrey8iuweqpoiuqtw[eoizsdfslknjvzxcknvl;/,asdmf;lkasdfj asldkf a/sldkf jwoieuofvahsdkj;fa;weio:KJSLDJIOWEJLKSJDFLWIUQOWUQ}R|)(_)(*+_)(*&^%$#@!~~!@#$%^&*()_+|}{POIUYTREWQASDFGHJKL:			ZXCVBNM<>? "" wijwfekjsdkfj sdfj zxcvbnm,./';lljhgfdsqwertyuiop[]\=-0987654321`asd;flkjghweqrey8iuweqpoiuqtw[eoizsdfslknjvzxcknvl;/,asdmf;lkasdfj asldkf a/sldkf jwoieuofvahsdkj;fa;weio:KJSLDJIOWEJLKSJDFLWIUQOWUQ}R|)(_)(*+_)(*&^%$#@!~~!@#$%^&*()_+|}{POIUYTREWQASDFGHJKL:			ZXCVBNM<>? "" wijwfekjsdkfj sdfj zxcvbnm,./';lljhgfdsqwertyuiop[]\=-0987654321`asd;flkjghweqrey8iuweqpoiuqtw[eoizsdfslknjvzxcknvl;/,asdmf;lkasdfj asldkf a/sldkf jwoieuofvahsdkj;fa;weio:KJSLDJIOWEJLKSJDFLWIUQOWUQ}R|)(_)(*+_)(*&^%$#@!~~!@#$%^&*()_+|}{POIUYTREWQASDFGHJKL:			ZXCVBNM<>? "" wijwfekjsdkfj sdfj zxcvbnm,./';lljhgfdsqwertyuiop[]\=-0987654321`asd;flkjghweqrey8iuweqpoiuqtw[eoizsdfslknjvzxcknvl;/,asdmf;lkasdfj asldkf a/sldkf jwoieuofvahsdkj;fa;weio:KJSLDJIOWEJLKSJDFLWIUQOWUQ}R|)(_)(*+_)(*&^%$#@!~~!@#$%^&*()_+|}{POIUYTREWQASDFGHJKL:			ZXCVBNM<>? "" wijwfekjsdkfj sdfj zxcvbnm,./';lljhgfdsqwertyuiop[]\=-0987654321`asd;flkjghweqrey8iuweqpoiuqtw[eoizsdfslknjvzxcknvl;/,asdmf;lkasdfj asldkf a/sldkf jwoieuofvahsdkj;fa;weio:KJSLDJIOWEJLKSJDFLWIUQOWUQ}R|)(_)(*+_)(*&^%$#@!~~!@#$%^&*()_+|}{POIUYTREWQASDFGHJKL:			ZXCVBNM<>? "" wijwfekjsdkfj sdfj zxcvbnm,./';lljhgfdsqwertyuiop[]\=-0987654321`asd;flkjghweqrey8iuweqpoiuqtw[eoizsdfslknjvzxcknvl;/,asdmf;lkasdfj asldkf a/sldkf jwoieuofvahsdkj;fa;weio:KJSLDJIOWEJLKSJDFLWIUQOWUQ}R|)(_)(*+_)(*&^%$#@!~~!@#$%^&*()_+|}{POIUYTREWQASDFGHJKL:			ZXCVBNM<>? "" wijwfekjsdkfj sdfj zxcvbnm,./';lljhgfdsqwertyuiop[]\=-0987654321`asd;flkjghweqrey8iuweqpoiuqtw[eoizsdfslknjvzxcknvl;/,asdmf;lkasdfj asldkf a/sldkf jwoieuofvahsdkj;fa;weio:KJSLDJIOWEJLKSJDFLWIUQOWUQ}R|)(_)(*+_)(*&^%$#@!~~!@#$%^&*()_+|}{POIUYTREWQASDFGHJKL:			ZXCVBNM<>? "" wijwfekjsdkfj sdfj zxcvbnm,./';lljhgfdsqwertyuiop[]\=-0987654321`asd;flkjghweqrey8iuweqpoiuqtw[eoizsdfslknjvzxcknvl;/,asdmf;lkasdfj asldkf a/sldkf jwoieuofvahsdkj;fa;weio:KJSLDJIOWEJLKSJDFLWIUQOWUQ}R|)(_)(*+_)(*&^%$#@!~~!@#$%^&*()_+|}{POIUYTREWQASDFGHJKL:			ZXCVBNM<>? "" wijwfekjsdkfj sdfj zxcvbnm,./';lljhgfdsqwertyuiop[]\=-0987654321`asd;flkjghweqrey8iuweqpoiuqtw[eoizsdfslknjvzxcknvl;/,asdmf;lkasdfj asldkf a/sldkf jwoieuofvahsdkj;fa;weio:KJSLDJIOWEJLKSJDFLWIUQOWUQ}R|)(_)(*+_)(*&^%$#@!~~!@#$%^&*()_+|}{POIUYTREWQASDFGHJKL:			ZXCVBNM<>? "" wijwfekjsdkfj sdfj zxcvbnm,./';lljhgfdsqwertyuiop[]\=-0987654321`asd;flkjghweqrey8iuweqpoiuqtw[eoizsdfslknjvzxcknvl;/,asdmf;lkasdfj asldkf a/sldkf jwoieuofvahsdkj;fa;weio:KJSLDJIOWEJLKSJDFLWIUQOWUQ}R|)(_)(*+_)(*&^%$#@!~~!@#$%^&*()_+|}{POIUYTREWQASDFGHJKL:			ZXCVBNM<>? "" wijwfekjsdkfj sdfj zxcvbnm,./';lljhgfdsqwertyuiop[]\=-0987654321`asd;flkjghweqrey8iuweqpoiuqtw[eoizsdfslknjvzxcknvl;/,asdmf;lkasdfj asldkf a/sldkf jwoieuofvahsdkj;fa;weio:KJSLDJIOWEJLKSJDFLWIUQOWUQ}R|)(_)(*+_)(*&^%$#@!~~!@#$%^&*()_+|}{POIUYTREWQASDFGHJKL:			ZXCVBNM<>? "" wijwfekjsdkfj sdfj zxcvbnm,./';lljhgfdsqwertyuiop[]\=-0987654321`asd;flkjghweqrey8iuweqpoiuqtw[eoizsdfslknjvzxcknvl;/,asdmf;lkasdfj asldkf a/sldkf jwoieuofvahsdkj;fa;weio:KJSLDJIOWEJLKSJDFLWIUQOWUQ}R|)(_)(*+_)(*&^%$#@!~~!@#$%^&*()_+|}{POIUYTREWQASDFGHJKL:			ZXCVBNM<>? "" wijwfekjsdkfj sdfj zxcvbnm,./';lljhgfdsqwertyuiop[]\=-0987654321`asd;flkjghweqrey8iuweqpoiuqtw[eoizsdfslknjvzxcknvl;/,asdmf;lkasdfj asldkf a/sldkf jwoieuofvahsdkj;fa;weio:KJSLDJIOWEJLKSJDFLWIUQOWUQ}R|)(_)(*+_)(*&^%$#@!~~!@#$%^&*()_+|}{POIUYTREWQASDFGHJKL:			ZXCVBNM<>? "" wijwfekjsdkfj sdfj zxcvbnm,./';lljhgfdsqwertyuiop[]\=-0987654321`asd;flkjghweqrey8iuweqpoiuqtw[eoizsdfslknjvzxcknvl;/,asdmf;lkasdfj asldkf a/sldkf jwoieuofvahsdkj;fa;weio:KJSLDJIOWEJLKSJDFLWIUQOWUQ}R|)(_)(*+_)(*&^%$#@!~~!@#$%^&*()_+|}{POIUYTREWQASDFGHJKL:			ZXCVBNM<>? "" wijwfekjsdkfj sdfj zxcvbnm,./';lljhgfdsqwertyuiop[]\=-0987654321`asd;flkjghweqrey8iuweqpoiuqtw[eoizsdfslknjvzxcknvl;/,asdmf;lkasdfj asldkf a/sldkf jwoieuofvahsdkj;fa;weio:KJSLDJIOWEJLKSJDFLWIUQOWUQ}R|)(_)(*+_)(*&^%$#@!~~!@#$%^&*()_+|}{POIUYTREWQASDFGHJKL:			ZXCVBNM<>? "" wijwfekjsdkfj sdfj zxcvbnm,./';lljhgfdsqwertyuiop[]\=-0987654321`asd;flkjghweqrey8iuweqpoiuqtw[eoizsdfslknjvzxcknvl;/,asdmf;lkasdfj asldkf a/sldkf jwoieuofvahsdkj;fa;weio:KJSLDJIOWEJLKSJDFLWIUQOWUQ}R|)(_)(*+_)(*&^%$#@!~~!@#$%^&*()_+|}{POIUYTREWQASDFGHJKL:			ZXCVBNM<>? "" wijwfekjsdkfj sdfj zxcvbnm,./';lljhgfdsqwertyuiop[]\=-0987654321`asd;flkjghweqrey8iuweqpoiuqtw[eoizsdfslknjvzxcknvl;/,asdmf;lkasdfj asldkf a/sldkf jwoieuofvahsdkj;fa;weio:KJSLDJIOWEJLKSJDFLWIUQOWUQ}R|)(_)(*+_)(*&^%$#@!~~!@#$%^&*()_+|}{POIUYTREWQASDFGHJKL:			ZXCVBNM<>? "" wijwfekjsdkfj sdfj zxcvbnm,./';lljhgfdsqwertyuiop[]\=-0987654321`asd;flkjghweqrey8iuweqpoiuqtw[eoizsdfslknjvzxcknvl;/,asdmf;lkasdfj asldkf a/sldkf jwoieuofvahsdkj;fa;weio:KJSLDJIOWEJLKSJDFLWIUQOWUQ}R|)(_)(*+_)(*&^%$#@!~~!@#$%^&*()_+|}{POIUYTREWQASDFGHJKL:			ZXCVBNM<>? "" wijwfekjsdkfj sdfj zxcvbnm,./';lljhgfdsqwertyuiop[]\=-0987654321`asd;flkjghweqrey8iuweqpoiuqtw[eoizsdfslknjvzxcknvl;/,asdmf;lkasdfj asldkf a/sldkf jwoieuofvahsdkj;fa;weio:KJSLDJIOWEJLKSJDFLWIUQOWUQ}R|)(_)(*+_)(*&^%$#@!~~!@#$%^&*()_+|}{POIUYTREWQASDFGHJKL:			ZXCVBNM<>? "" wijwfekjsdkfj sdfj zxcvbnm,./';lljhgfdsqwertyuiop[]\=-0987654321`asd;flkjghweqrey8iuweqpoiuqtw[eoizsdfslknjvzxcknvl;/,asdmf;lkasdfj asldkf a/sldkf jwoieuofvahsdkj;fa;weio:KJSLDJIOWEJLKSJDFLWIUQOWUQ}R|)(_)(*+_)(*&^%$#@!~~!@#$%^&*()_+|}{POIUYTREWQASDFGHJKL:			ZXCVBNM<>? "" wijwfekjsdkfj sdfj zxcvbnm,./';lljhgfdsqwertyuiop[]\=-0987654321`asd;flkjghweqrey8iuweqpoiuqtw[eoizsdfslknjvzxcknvl;/,asdmf;lkasdfj asldkf a/sldkf jwoieuofvahsdkj;fa;weio:KJSLDJIOWEJLKSJDFLWIUQOWUQ}R|)(_)(*+_)(*&^%$#@!~~!@#$%^&*()_+|}{POIUYTREWQASDFGHJKL:			ZXCVBNM<>? "" wijwfekjsdkfj sdfj zxcvbnm,./';lljhgfdsqwertyuiop[]\=-0987654321`";
            #endregion

            PhraseEdit newPhraseEdit    = null;
            PhraseEdit savedPhraseEdit  = null;
            PhraseEdit gottenPhraseEdit = null;


            var isAsyncComplete = false;
            var hasError        = false;
            EnqueueConditional(() => isAsyncComplete);
            await Setup();

            try
            {
                //NEW
                newPhraseEdit = await PhraseEdit.NewPhraseEditAsync();

                //EDIT
                newPhraseEdit.Text     = reallyLongText;
                newPhraseEdit.UserId   = SeedData.Ton.GetTestValidUserDto().Id;
                newPhraseEdit.Username = SeedData.Ton.TestValidUsername;
                Assert.AreEqual(SeedData.Ton.EnglishId, newPhraseEdit.LanguageId);

                //SAVE
                savedPhraseEdit = await newPhraseEdit.SaveAsync();

                //GET (CONFIRM SAVE)
                gottenPhraseEdit = await PhraseEdit.GetPhraseEditAsync(savedPhraseEdit.Id);
            }
            catch
            {
                hasError = true;
            }
            finally
            {
                EnqueueCallback(
                    () => Assert.IsFalse(hasError),
                    () => Assert.IsNotNull(newPhraseEdit),
                    () => Assert.IsNotNull(savedPhraseEdit),
                    () => Assert.IsNotNull(gottenPhraseEdit),
                    () => Assert.AreEqual(savedPhraseEdit.Id, gottenPhraseEdit.Id),
                    () => Assert.AreEqual(savedPhraseEdit.Text, gottenPhraseEdit.Text)
                    );
                EnqueueTestComplete();
                Teardown();
                isAsyncComplete = true;
            }
        }
        public async Task NEW_EDIT_BEGINSAVE_GET()
        {
            PhraseEdit newPhraseEdit    = null;
            PhraseEdit savedPhraseEdit  = null;
            PhraseEdit gottenPhraseEdit = null;

            var isAsyncComplete = false;
            var hasError        = false;

            EnqueueConditional(() => isAsyncComplete);
            await Setup();

            try
            {
                //NEW
                newPhraseEdit = await PhraseEdit.NewPhraseEditAsync();

                //EDIT
                newPhraseEdit.Text     = "TestPhrase NEW_EDIT_BEGINSAVE_GET";
                newPhraseEdit.UserId   = SeedData.Ton.GetTestValidUserDto().Id;
                newPhraseEdit.Username = SeedData.Ton.TestValidUsername;

                //SAVE
                savedPhraseEdit = await newPhraseEdit.SaveAsync();

                //GET (CONFIRM SAVE)
                gottenPhraseEdit = await PhraseEdit.GetPhraseEditAsync(savedPhraseEdit.Id);
            }
            catch
            {
                hasError = true;
            }
            finally
            {
                EnqueueCallback(
                    () => Assert.IsFalse(hasError),
                    () => Assert.IsNotNull(newPhraseEdit),
                    () => Assert.IsNotNull(savedPhraseEdit),
                    () => Assert.IsNotNull(gottenPhraseEdit),
                    () => Assert.AreEqual(savedPhraseEdit.Id, gottenPhraseEdit.Id),
                    () => Assert.AreEqual(savedPhraseEdit.Text, gottenPhraseEdit.Text)
                    );

                EnqueueTestComplete();
                Teardown();
                isAsyncComplete = true;
            }
        }
        public async Task MAKE_PHRASE_WITH_REALLY_REALLY_LONG_NUMERICAL_TEXT()
        {
            var maxLength = 300000; //worked

            maxLength = 100000;     //worked
            maxLength = 30000;      //just for a big number, to lessen time to do test.
            var    i = 0;
            string reallyReallyLongText = "";

            while (reallyReallyLongText.Length < maxLength)
            {
                reallyReallyLongText += i.ToString();
                i++;
                if (i == maxLength) //shouldn't happen, but no big deal if it does. It's just a reallyraeallyreallyreally long text.
                {
                    break;
                }
            }
            if (reallyReallyLongText.Length > maxLength)
            {
                reallyReallyLongText = reallyReallyLongText.Substring(0, maxLength);
            }

            PhraseEdit newPhraseEdit    = null;
            PhraseEdit savedPhraseEdit  = null;
            PhraseEdit gottenPhraseEdit = null;

            var isAsyncComplete = false;
            var hasError        = false;

            EnqueueConditional(() => isAsyncComplete);
            await Setup();

            try
            {
                //NEW
                newPhraseEdit = await PhraseEdit.NewPhraseEditAsync();

                //EDIT
                newPhraseEdit.Text     = reallyReallyLongText;
                newPhraseEdit.UserId   = SeedData.Ton.GetTestValidUserDto().Id;
                newPhraseEdit.Username = SeedData.Ton.TestValidUsername;

                //SAVE
                savedPhraseEdit = await newPhraseEdit.SaveAsync();

                //GET (CONFIRM SAVE)
                gottenPhraseEdit = await PhraseEdit.GetPhraseEditAsync(savedPhraseEdit.Id);
            }
            catch
            {
                hasError = true;
            }
            finally
            {
                EnqueueCallback(
                    () => Assert.IsFalse(hasError),
                    () => Assert.IsNotNull(newPhraseEdit),
                    () => Assert.IsNotNull(savedPhraseEdit),
                    () => Assert.IsNotNull(gottenPhraseEdit),
                    () => Assert.AreEqual(savedPhraseEdit.Id, gottenPhraseEdit.Id),
                    () => Assert.AreEqual(reallyReallyLongText.Length, gottenPhraseEdit.Text.Length),
                    () => Assert.AreEqual(savedPhraseEdit.Text, gottenPhraseEdit.Text)
                    );

                EnqueueTestComplete();
                Teardown();
                isAsyncComplete = true;
            }
        }
        public async Task NEW_EDIT_BEGINSAVE_GET_DELETE_GET()
        {
            PhraseEdit newPhraseEdit     = null;
            PhraseEdit savedPhraseEdit   = null;
            PhraseEdit gottenPhraseEdit  = null;
            PhraseEdit deletedPhraseEdit = null;

            //INITIALIZE TO EMPTY Phrase EDIT, BECAUSE WE EXPECT THIS TO BE NULL LATER
            PhraseEdit deleteConfirmedPhraseEdit = new PhraseEdit();

            var isAsyncComplete = false;
            var hasError        = false;

            EnqueueConditional(() => isAsyncComplete);
            await Setup();

            try
            {
                //NEW
                newPhraseEdit = await PhraseEdit.NewPhraseEditAsync();

                //EDIT
                newPhraseEdit.Text     = "TestPhrase NEW_EDIT_BEGINSAVE_GET_DELETE_GET";
                newPhraseEdit.UserId   = SeedData.Ton.GetTestValidUserDto().Id;
                newPhraseEdit.Username = SeedData.Ton.TestValidUsername;

                //SAVE
                savedPhraseEdit = await newPhraseEdit.SaveAsync();

                //GET (CONFIRM SAVE)
                gottenPhraseEdit = await PhraseEdit.GetPhraseEditAsync(savedPhraseEdit.Id);

                //DELETE (MARKS DELETE.  SAVE INITIATES ACTUAL DELETE IN DB)
                gottenPhraseEdit.Delete();
                deletedPhraseEdit = await gottenPhraseEdit.SaveAsync();

                try
                {
                    deleteConfirmedPhraseEdit = await PhraseEdit.GetPhraseEditAsync(deletedPhraseEdit.Id);
                }
                catch (Csla.DataPortalException dpex)
                {
                    var debugExecutionLocation        = Csla.ApplicationContext.ExecutionLocation;
                    var debugLogicalExecutionLocation = Csla.ApplicationContext.LogicalExecutionLocation;
                    //WE EXPECT AN ID NOT FOUND EXCEPTION. IF SOMETHING ELSE, RETHROW IT.
                    if (!TestsHelper.IsIdNotFoundException(dpex))
                    {
                        throw dpex;
                    }
                }
            }
            catch
            {
                hasError = true;
            }
            finally
            {
                EnqueueCallback(
                    () => Assert.IsFalse(hasError),
                    () => Assert.IsNotNull(newPhraseEdit),
                    () => Assert.IsNotNull(savedPhraseEdit),
                    () => Assert.IsNotNull(gottenPhraseEdit),
                    () => Assert.IsNotNull(deletedPhraseEdit),
                    () => Assert.AreEqual(Guid.Empty, deleteConfirmedPhraseEdit.Id),
                    () => Assert.AreEqual(Guid.Empty, deleteConfirmedPhraseEdit.LanguageId),
                    () => Assert.AreEqual(Guid.Empty, deleteConfirmedPhraseEdit.UserId),
                    () => Assert.AreEqual(string.Empty, deleteConfirmedPhraseEdit.Username)
                    );

                EnqueueTestComplete();
                Teardown();
                isAsyncComplete = true;
            }
        }
        /// <summary>
        /// Gets the most recent phrase beliefs for all of the current user's phrases.
        /// </summary>
        /// <returns></returns>
        private async Task <PhraseEdit> GetRandomUnknownPhrase(MultiLineTextList multiLineTextList)
        {
            History.Events.ThinkingAboutTargetEvent.Publish(System.Guid.Empty);

            if (_MostRecentPhraseBeliefsCache == null)
            {
                throw new Exception("MostRecentPhraseBeliefsCache should not be null");
            }
            if (_PseudoBeliefsCache == null)
            {
                _PseudoBeliefsCache = new MobileDictionary <string, Tuple <string, double> >();
            }

            PhraseEdit retPhrase = null;

            //GET OUR UNKNOWNS OUT OF OUR CACHES
            var threshold = double.Parse(StudyResources.DefaultKnowledgeThreshold);
            var unknownBeliefsFromCache = (from belief in _MostRecentPhraseBeliefsCache
                                           where belief.Strength < threshold &&
                                           PhraseTextIsInMultiLineTextList(belief.Phrase.Text, multiLineTextList)
                                           select belief).ToList();
            var unknownPseudoBeliefsFromCache = (from entry in _PseudoBeliefsCache
                                                 where entry.Value.Item2 < threshold &&
                                                 PhraseTextIsInMultiLineTextList(entry.Key, multiLineTextList)
                                                 select entry).ToList();

            //GET OUR UNKNOWN PHRASES THAT DONT HAVE A BELIEF OR PSUEDO BELIEF REGISTERED WITH THEM YET
            var unregisteredUnknownPhrases = GetUnregisteredUnknownPhraseBeliefs(multiLineTextList,
                                                                                 unknownBeliefsFromCache,
                                                                                 unknownPseudoBeliefsFromCache);

            var indexToPick = -1;
            //TOTAL COUNT = MOST RECENT PHRASE BELIEFS + PSEUDO BELIEFS COUNT + PHRASES WITHOUT BELIEFS
            var totalCountUnknown = 0;

            totalCountUnknown += unknownBeliefsFromCache.Count;
            if (_PseudoBeliefsCache != null)
            {
                totalCountUnknown += unknownPseudoBeliefsFromCache.Count;
            }
            totalCountUnknown += unregisteredUnknownPhrases.Count;

            if (totalCountUnknown == 0)
            {
                //EVERYTHING IS KNOWN, SO RETURN NULL
                return(null);
            }

            //IF WE TRY TO PICK FROM THE PSEUDO CACHE, THEN IT IS POSSIBLE
            //THAT OUR PHRASETEXT NO LONGER MATCHES A PHRASE. THEREFORE, WE
            //SET UP A LOOP TO KEEP TRYING TO PICK A RANDOM PHRASE FROM THE
            //ENTIRE LIST OF BOTH CACHES. IF WE FAIL TO DO THIS, THEN WE WILL
            //PICK FROM JUST THE ACTUAL BELIEF CACHE (NOT THE PSEUDO).
            var maxTries = int.Parse(StudyResources.MaxTriesToPickRandomFromEntireList);

            for (int i = 0; i < maxTries; i++)
            {
                History.Events.ThinkingAboutTargetEvent.Publish(System.Guid.Empty);

                indexToPick = RandomPicker.Ton.NextInt(0, totalCountUnknown);

                if (indexToPick < unknownBeliefsFromCache.Count)
                {
                    //WE PICK FROM THE PHRASE BELIEF CACHE
                    var belief = unknownBeliefsFromCache[indexToPick];
                    return(belief.Phrase);
                }
                else if (indexToPick < (unknownBeliefsFromCache.Count + unknownPseudoBeliefsFromCache.Count))
                {
                    //WE _TRY_ TO PICK FROM THE PSUEDO CACHE
                    indexToPick -= unknownBeliefsFromCache.Count;
                    var beliefEntry  = unknownPseudoBeliefsFromCache[indexToPick];
                    var phraseText   = beliefEntry.Key;
                    var languageText = beliefEntry.Value.Item1;
                    var phrase       = await PhraseEdit.NewPhraseEditAsync(languageText);

                    phrase.Text = phraseText;
                    var phraseId = Guid.NewGuid();
                    phrase.Id = phraseId;
                    var retriever = await PhrasesByTextAndLanguageRetriever.CreateNewAsync(phrase);

                    retPhrase = retriever.RetrievedSinglePhrase;
                    if (retPhrase != null)
                    {
                        //WE HAVE FOUND A RETURN PHRASE, SO BREAK OUT OF OUR ATTEMPT LOOP
                        return(retPhrase);
                    }
                }
                else
                {
                    //WE PICK FROM THE UNKNOWN PHRASES WITHOUT BELIEFS I'M CONVERTING THIS
                    //TO LIST THIS LATE BECAUSE WE DON'T NEED IT AS A LIST UNTIL NOW.
                    var asList = unregisteredUnknownPhrases.ToList();
                    indexToPick -= (unknownBeliefsFromCache.Count + unknownPseudoBeliefsFromCache.Count);
                    retPhrase    = unregisteredUnknownPhrases[indexToPick];
                    return(retPhrase);
                }
            }

            //IF WE'VE GOTTEN THIS FAR, THEN WE COULDN'T FIND AN UNKNOWN PHRASE
            Services.PublishMessageEvent("Couldn't retrieve unknown phrase.", MessagePriority.Medium, MessageType.Warning);
            return(null);
        }
        public async Task SaveAnswer()
        {
            AnswerIsReadOnly          = true;
            SaveAnswerButtonIsEnabled = false;

            #region Thinking (try..)
            var targetId = Guid.NewGuid();
            History.Events.ThinkingAboutTargetEvent.Publish(targetId);
            DisableNavigationRequestedEventMessage.Publish();
            try
            {
                #endregion
                #region Get the DB version of answer, then modify it and save

                //STORE OUR MODIFIED TEXT
                _ModifiedAnswerText = Answer.Text;

                //PREPARE ANSWER TO BE SEARCHED FOR IN DB
                Answer.Text = _InitialAnswerText;
                PhrasesByTextAndLanguageRetriever retriever = null;
                #region SEARCH IN DB FOR ANSWER (WITH INITIAL TEXT)
                History.Events.ThinkingAboutTargetEvent.Publish(System.Guid.Empty);
                {
                    retriever = await Business.PhrasesByTextAndLanguageRetriever.CreateNewAsync(Answer);
                }
                History.Events.ThinkingAboutTargetEvent.Publish(System.Guid.Empty);

                var dbAnswer = retriever.RetrievedSinglePhrase;
                if (dbAnswer == null)
                {
                    //ANSWER NOT IN DB, BUT ANSWER IS A CHILD
                    if (Answer.IsChild)
                    {
                        //CANNOT SAVE THE ANSWER DIRECTLY BECAUSE IT IS A CHILD
                        #region CREATE NEW PHRASE EDIT, LOAD FROM ANSWER DTO, SAVE ANSWER
                        var newAnswerObj = await PhraseEdit.NewPhraseEditAsync();

                        Answer.Text = _ModifiedAnswerText;
                        var dto = Answer.CreateDto();
                        dto.Id = Guid.NewGuid();

                        newAnswerObj.LoadFromDtoBypassPropertyChecks(dto);
                        Answer = newAnswerObj;

                        #region Save Answer
                        Answer = await Answer.SaveAsync();

                        _InitialAnswerText        = Answer.Text;
                        _ModifiedAnswerText       = "";
                        SaveAnswerButtonIsEnabled = true;
                        AnswerIsReadOnly          = true;
                        UpdateEditAnswerButtonVisibilities();
                        #endregion
                        #endregion
                    }
                    //ANSWER NOT IN DB, BUT ANSWER IS NOT A CHILD
                    else
                    {
                        #region SAVE THE ANSWER DIRECTLY, B/C IT IS NOT A CHILD
                        Answer = await Answer.SaveAsync();

                        _InitialAnswerText        = Answer.Text;
                        _ModifiedAnswerText       = "";
                        SaveAnswerButtonIsEnabled = true;
                        AnswerIsReadOnly          = true;
                        UpdateEditAnswerButtonVisibilities();
                        #endregion
                    }
                }
                //ANSWER WAS FOUND IN DB
                else
                {
                    #region REASSIGN THE ANSWER WITH THE DBANSWER, SAVE WITH THE MODIFIED TEXT
                    Answer      = dbAnswer;
                    Answer.Text = _ModifiedAnswerText;
                    Answer      = await Answer.SaveAsync();

                    _InitialAnswerText        = Answer.Text;
                    _ModifiedAnswerText       = "";
                    SaveAnswerButtonIsEnabled = true;
                    AnswerIsReadOnly          = true;
                    UpdateEditAnswerButtonVisibilities();
                    #endregion
                }

                #endregion

                #endregion
                #region (...finally) Thinked
            }
            finally
            {
                EnableNavigationRequestedEventMessage.Publish();
                History.Events.ThinkedAboutTargetEvent.Publish(targetId);
            }
            #endregion
        }
        public async Task SaveQuestion()
        {
            QuestionIsReadOnly          = true;
            SaveQuestionButtonIsEnabled = false;
            #region Thinking (try..)
            var targetId = Guid.NewGuid();
            History.Events.ThinkingAboutTargetEvent.Publish(targetId);
            DisableNavigationRequestedEventMessage.Publish();
            try
            {
                #endregion

                #region Get the DB version of question, then modify it and save

                //STORE OUR MODIFIED TEXT
                _ModifiedQuestionText = Question.Text;

                //PREPARE QUESTION TO BE SEARCHED FOR IN DB
                Question.Text = _InitialQuestionText;

                #region SEARCH IN DB FOR QUESTION (WITH INITIAL TEXT)
                PhrasesByTextAndLanguageRetriever retriever = null;
                History.Events.ThinkingAboutTargetEvent.Publish(System.Guid.Empty);
                {
                    retriever = await Business.PhrasesByTextAndLanguageRetriever.CreateNewAsync(Question);
                }
                History.Events.ThinkingAboutTargetEvent.Publish(System.Guid.Empty);

                var dbQuestion = retriever.RetrievedSinglePhrase;
                if (dbQuestion == null)
                {
                    //QUESTION NOT IN DB, BUT QUESTION IS A CHILD
                    if (Question.IsChild)
                    {
                        //CANNOT SAVE THE QUESTION DIRECTLY BECAUSE IT IS A CHILD
                        #region CREATE NEW PHRASE EDIT, LOAD FROM QUESTION DTO, SAVE QUESTION
                        var newQuestionObj = await PhraseEdit.NewPhraseEditAsync();

                        Question.Text = _ModifiedQuestionText;
                        var dto = Question.CreateDto();
                        dto.Id = Guid.NewGuid();

                        newQuestionObj.LoadFromDtoBypassPropertyChecks(dto);
                        Question = newQuestionObj;

                        #region Save Question
                        Question = await Question.SaveAsync();

                        _InitialQuestionText        = Question.Text;
                        _ModifiedQuestionText       = "";
                        SaveQuestionButtonIsEnabled = true;
                        QuestionIsReadOnly          = true;
                        UpdateEditQuestionButtonVisibilities();
                        #endregion
                        #endregion
                    }
                    //QUESTION NOT IN DB, BUT QUESTION IS NOT A CHILD
                    else
                    {
                        #region SAVE THE QUESTION DIRECTLY, B/C IT IS NOT A CHILD
                        Question = await Question.SaveAsync();

                        _InitialQuestionText        = Question.Text;
                        _ModifiedQuestionText       = "";
                        SaveQuestionButtonIsEnabled = true;
                        QuestionIsReadOnly          = true;
                        UpdateEditQuestionButtonVisibilities();
                        #endregion
                    }
                }
                //QUESTION WAS FOUND IN DB
                else
                {
                    #region REASSIGN THE QUESTION WITH THE DBQUESTION, SAVE WITH THE MODIFIED TEXT
                    Question      = dbQuestion;
                    Question.Text = _ModifiedQuestionText;
                    Question      = await Question.SaveAsync();

                    _InitialQuestionText        = Question.Text;
                    _ModifiedQuestionText       = "";
                    SaveQuestionButtonIsEnabled = true;
                    QuestionIsReadOnly          = true;
                    UpdateEditQuestionButtonVisibilities();
                    #endregion
                }

                #endregion

                #endregion
                #region (...finally) Thinked
            }
            finally
            {
                EnableNavigationRequestedEventMessage.Publish();
                History.Events.ThinkedAboutTargetEvent.Publish(targetId);
            }
            #endregion
        }