2

I'm making a call to Yelp, to get reviews for some addresses in an apartment finder I've written, but it looks like some of the Yelp data isn't complete, so the following code results in Ye Olde ORNSTAIOAN error:

    public IEnumerable<Review> GetReviews(Bounds searchBounds) {
        var yelp = new Y.Yelp(ConfigOptions);
        var searchOptions = GetSearchOptions(searchBounds);
        var searchTask = yelp.Search(searchOptions);
        var tasks = new Task<Y.Data.SearchResults>[GetTaskArraySize(searchTask)];

        tasks[0] = searchTask;

        for (var i = 1; i < tasks.Length; i++) {
            searchOptions.GeneralOptions.offset = i * YelpResultsLimit;
            tasks[i] = yelp.Search(searchOptions);
        }

        Task.WaitAll(tasks);

        return tasks.SelectMany(t => t.Result.businesses != null
            ? t.Result.businesses
            : null)
                    .Select(MapYelpBusinessToReview);
    }

The error hits in the return line, on "businesses", even if I try a null catch, as I am above. The error outputs as:

<Error>
    <script id="tinyhippos-injected"/>
    <Message>
        An error has occurred.
    </Message>
    <ExceptionMessage>
        Object reference not set to an instance of an object.
    </ExceptionMessage>
    <ExceptionType>
        System.NullReferenceException
    </ExceptionType>
    <StackTrace>
        at System.Linq.Enumerable.<SelectManyIterator>d__14`2.MoveNext() at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext() at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source) at ApartmentFinder.Infrastructure.Services.SearchEngine.<>c__DisplayClassc.<FindProperties>b__1() in c:\Development\myProject\ApartmentFinder.Infrastructure\Services\SearchEngine.cs:line 25 at System.Threading.Tasks.Task`1.InnerInvoke() at System.Threading.Tasks.Task.Execute()
    </StackTrace>
</Error>

How can I trap the missing business information, and proceed with/without it?

Update:

YelpSharp.Data.Business

namespace ApartmentFinder.Infrastructure.Models {
    /// <summary>
    /// Provides the set of properties describing a review for a property.
    /// </summary>
    public class Review {
        public string Id{ get; set; }
        public string Name{ get; set; }
        public string Address{ get; set; }
        public string City{ get; set; }
        public string State{ get; set; }
        public string ZipCode{ get; set; }
        public string PhoneNumber{ get; set; }
        public string RatingImageUrl{ get; set; }
        public int NumberOfReviews{ get; set; }
        public string Snippet{ get; set; }
        public string Url{ get; set; }
        public double Latitude{ get; set; }
        public double Longitude{ get; set; }
    }
}

Adding in the method for Review MapYelpBusinessToReview:

    /// <summary>
    /// Maps a <see cref="Y.Data.Business"/> instance to a new <see cref="Review"/>.
    /// </summary>
    /// <param name="business">Business object to map.</param>
    /// <returns>A new <see cref="Review"/> instance.</returns>
    static Review MapYelpBusinessToReview(Y.Data.Business business) {
        return new Review {
            Id = business.id,
            Name = business.name,
            Address = business.location.address[0],
            City = business.location.city,
            State = business.location.state_code,
            ZipCode = business.location.postal_code,
            PhoneNumber = business.phone,
            RatingImageUrl = business.rating_img_url,
            Snippet = business.snippet_text,
            Url = business.url,
            NumberOfReviews = business.review_count,

        };
    }
PKD
  • 685
  • 1
  • 13
  • 37

1 Answers1

2

The problem is that in the SelectMany call you end up returning a null value instead of an empty collection to. In the case you want no values added you must return an empty collection else SelectMany will null ref

Try the following

return tasks
  .SelectMany(t => t.Result.businesses ?? new List<Business>())
  .Select(MapYelpBusinessToReview);
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
  • I see where you're going on this, but the issue I run into with that is: `Operator '??' cannot be applied to operands of type 'System.Collections.Generic.List' and 'ApartmentFinder.Infrastructure.Models.Review[]'` (Adding view of YelpSharp.Data.Business, and Review above) – PKD Mar 03 '14 at 17:15
  • @PKD fixed that error. Just needed to change the type to `List` to match the left hand side – JaredPar Mar 03 '14 at 17:17
  • Heh! Quick on the draw. – PKD Mar 03 '14 at 17:18
  • `Operator '??' cannot be applied to operands of type 'System.Collections.Generic.List' and 'System.Collections.Generic.List'` – PKD Mar 03 '14 at 17:19
  • @PKD ah, missed that the mapping occured on the following `Select` – JaredPar Mar 03 '14 at 17:19
  • Any other ideas on this? I feel like it's really close! :) – PKD Mar 04 '14 at 18:09
  • Heya, @JaredPar - Any more thoughts on this? – PKD Mar 06 '14 at 16:48
  • @PKD what's the problem at this point? It looks like it should work here – JaredPar Mar 06 '14 at 18:27
  • @PKD the current code should fix that. The types on both the left and right of `??` are `List` now. – JaredPar Mar 07 '14 at 05:32
  • @PKD it was 4 days ago but now both sides should be of the same type. If they aren't you simply need to make the `new List` call have the correct type in there. Based on the error message it needs to be either Business or Review. I've posted both as answers and you seem to be rejecting both of them. Something is amiss here because they are the only 2 correct ansewrs based on the error messages you are posting – JaredPar Mar 07 '14 at 18:46
  • I'm not rejecting anything, but when I've tried your solutions, they've resulted in more errors. I've tried working through them, but the result has been even more errors. :) So, your current solution is: `return tasks .SelectMany(t => t.Result.businesses ?? new List()) .Select(MapYelpBusinessToReview);`. I'll try it again today, and see where I get to with it. – PKD Mar 10 '14 at 15:52
  • @PKD but what are the new errors? So far you've only posted the one which I've seemingly solved. – JaredPar Mar 10 '14 at 15:53
  • Ok - using `return tasks.SelectMany(t => t.Result.businesses ?? new List()).Select(MapYelpBusinessToReview);`, and it works! You rock, man. It had an error at first, but I resolved that with a reference, and blammo, all's well! – PKD Mar 10 '14 at 17:37
  • The reference to resolve the final error was to add `using YelpSharp.Data;` and `using YelpSharp.Data.Options;` in my usings. – PKD Mar 10 '14 at 17:39
  • Now, @JaredPar, if you were also a god of KendoUI, and MVC Razor... I'd have another one in another project to ask you about. :) – PKD Mar 10 '14 at 17:40