How can I safely loop until there is nothing more to do without using a “placeholder” while conditon?

In order to call my Web API method until no more data is returned (I'm fetching it in batches, to keep each result set small, due to the 98-lb-weakling persona of the client (Windows CE handheld device)), I'm using this code:

while (moreRecordsExist)
{
    redemptionsList.redemptions.Clear();
    string uri = String.Format("http://platypus:28642/api/Redemptions/{0}/{1}", lastIdFetched, RECORDS_TO_FETCH);
    var webRequest = (HttpWebRequest)WebRequest.Create(uri);
    webRequest.Method = "GET";

    using (var webResponse = (HttpWebResponse)webRequest.GetResponse())
    {
        if (webResponse.StatusCode == HttpStatusCode.OK)
        {
            var reader = new StreamReader(webResponse.GetResponseStream());
            string s = reader.ReadToEnd();
            var arr = JsonConvert.DeserializeObject<JArray>(s);
            if (null == arr) break;

            foreach (JObject obj in arr)
            {
                id = obj.Value<int?>("Id") ?? 0;
                var _redemptionId = obj.Value<string>("RedemptionId") ?? "";
                var _redemptionItemId = obj.Value<string>("RedemptionItemId") ?? "";
                var _redemptionName = obj.Value<string>("RedemptionName") ?? "";
                double _redemptionAmount = obj.Value<double?>("RedemptionAmount") ?? 0.0;
                var _redemptionDept = obj.Value<string>("RedemptionDept") ?? "";
                var _redemptionSubdept = obj.Value<string>("RedemptionSubDept") ?? "";

                redemptionsList.redemptions.Add(new HHSUtils.Redemption
                {
                    Id = id,
                    RedemptionId = _redemptionId,
                    RedemptionItemId = _redemptionItemId,
                    RedemptionName = _redemptionName,
                    RedemptionAmount = _redemptionAmount,
                    RedemptionDept = _redemptionDept,
                    RedemptionSubDept = _redemptionSubdept,
                });
            } // foreach
        } // if ((webResponse.StatusCode == HttpStatusCode.OK) && (webResponse.ContentLength > 2))
    } // using HttpWebResponse
    int recordsAdded = LocalDBUtils.BulkInsertRedemptions(redemptionsList.redemptions);
    totalRecordsAdded += recordsAdded;
    //moreRecordsExist = (recordsToFetch > (totalRecordsAdded));
    lastIdFetched = id;
} // while

This works (if I check webResponse for null, it crashes with a NullReferenceException), but I don't really like my while loop, as it is never reached once moreRecordsExist is assigned false. So, I set the Resharper hounds loose on it to see if it had a better suggestion, but it just tells me, "Expression is always true" for that line, and the suggested "fix" for this is to change it to "while (true)"

I fail to see how that is much of an improvement, though.

Is there a way I can accomplish the same thing with a more sensible construct?

Answers


You break out the loop with a break statement immediately after assigning false to moreRecordsExist variable, so its value will never be false in the beginning of the loop. You can make a change as ReSharper suggests and get rid of moreRecordsExist variable:

while (true)
{
    redemptionsList.redemptions.Clear();
    string uri = String.Format("http://platypus:28642/api/Redemptions/{0}/{1}", lastIdFetched, RECORDS_TO_FETCH);
    var webRequest = (HttpWebRequest)WebRequest.Create(uri);
    webRequest.Method = "GET";

    using (var webResponse = (HttpWebResponse)webRequest.GetResponse())
    {
        if (webResponse.StatusCode == HttpStatusCode.OK)
        {
            var reader = new StreamReader(webResponse.GetResponseStream());
            string s = reader.ReadToEnd();
            var arr = JsonConvert.DeserializeObject<JArray>(s);
            if (arr == null) break;

            foreach (JObject obj in arr)
            {
                id = obj.Value<int?>("Id") ?? 0;
                var _redemptionId = obj.Value<string>("RedemptionId") ?? "";
                var _redemptionItemId = obj.Value<string>("RedemptionItemId") ?? "";
                var _redemptionName = obj.Value<string>("RedemptionName") ?? "";
                double _redemptionAmount = obj.Value<double?>("RedemptionAmount") ?? 0.0;
                var _redemptionDept = obj.Value<string>("RedemptionDept") ?? "";
                var _redemptionSubdept = obj.Value<string>("RedemptionSubDept") ?? "";

                redemptionsList.redemptions.Add(new HHSUtils.Redemption
                {
                    Id = id,
                    RedemptionId = _redemptionId,
                    RedemptionItemId = _redemptionItemId,
                    RedemptionName = _redemptionName,
                    RedemptionAmount = _redemptionAmount,
                    RedemptionDept = _redemptionDept,
                    RedemptionSubDept = _redemptionSubdept,
                });
            } // foreach
        } // if ((webResponse.StatusCode == HttpStatusCode.OK) && (webResponse.ContentLength > 2))
    } // using HttpWebResponse
    int recordsAdded = LocalDBUtils.BulkInsertRedemptions(redemptionsList.redemptions);
    totalRecordsAdded += recordsAdded;
    //moreRecordsExist = (recordsToFetch > (totalRecordsAdded));
    lastIdFetched = id;
} // while

Why not return some metadata with response, e.g. {Pages:10} ? Then you know exactly how many records you're going after.


Consider using a do..while() loop. This gets you around the "while-loop-is-never-reached" problem... it will always run at least once, no matter what moreRecordsExist is set to.

do
{
    redemptionsList.redemptions.Clear();
    string uri = String.Format("http://platypus:28642/api/Redemptions/{0}/{1}",     lastIdFetched, RECORDS_TO_FETCH);
    var webRequest = (HttpWebRequest)WebRequest.Create(uri);
    webRequest.Method = "GET";

    using (var webResponse = (HttpWebResponse)webRequest.GetResponse())
    {
        if (webResponse.StatusCode == HttpStatusCode.OK)
        {
            var reader = new StreamReader(webResponse.GetResponseStream());
            string s = reader.ReadToEnd();
            var arr = JsonConvert.DeserializeObject<JArray>(s);
            if (arr == null) break;

            foreach (JObject obj in arr)
            {
                id = obj.Value<int?>("Id") ?? 0;
                var _redemptionId = obj.Value<string>("RedemptionId") ?? "";
                var _redemptionItemId = obj.Value<string>("RedemptionItemId") ?? "";
                var _redemptionName = obj.Value<string>("RedemptionName") ?? "";
                double _redemptionAmount = obj.Value<double?>("RedemptionAmount") ?? 0.0;    
                var _redemptionDept = obj.Value<string>("RedemptionDept") ?? "";
                var _redemptionSubdept = obj.Value<string>("RedemptionSubDept") ?? "";

                redemptionsList.redemptions.Add(new HHSUtils.Redemption
                {
                    Id = id,
                    RedemptionId = _redemptionId,
                    RedemptionItemId = _redemptionItemId,
                    RedemptionName = _redemptionName,
                    RedemptionAmount = _redemptionAmount,
                    RedemptionDept = _redemptionDept,
                    RedemptionSubDept = _redemptionSubdept,
                });
            } // foreach
        } // if ((webResponse.StatusCode == HttpStatusCode.OK) && (webResponse.ContentLength > 2))
    } // using HttpWebResponse
    int recordsAdded = LocalDBUtils.BulkInsertRedemptions(redemptionsList.redemptions);
    totalRecordsAdded += recordsAdded;
    moreRecordsExist = (recordsToFetch > (totalRecordsAdded));
    lastIdFetched = id;
} while (moreRecordsExist);

Need Your Help

Loading/Saving Word Documents from Web App (asp.net MVC)

asp.net asp.net-mvc sharepoint ms-word webdav

I'm making a web app. Part of it includes the automatic generation of word documents (letters). Those documents need to be opened by the end user, then saved back to the server once they've finis...

Application fails to apple but works for me

iphone mobile app-store submission

I loaded an application to app store and they sent me an email telling me that the application crashes, but I run it on debug and release mode and it works, do you know what could be the problem?.

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.