0

I have a settings table with two columns, "Name" and "Value":

Name       | Value
-----------+-------
start_time | 9:30
end_time   | 4:30
length     |   30

I also have a result set that gives the number of appointments per time period:

count | time
------+--------
1     | 09:30
2     | 12:00
3     | 14:00
4     | 15:30

And I need to show all the time slots between start_time and end_time, with their number of appointments like this:

(1) 09:30
    10:30
    11:00
    11:30
(2) 12:00
    12:30
    13:00
    13:30
(3) 14:00
    14:30
    15:00
(4) 15:30

Here's what I got:

// data is the result of WebMatrix.Data.Database.Query
public void PrepareHTML(dynamic data) 
{
    StringBuilder SB = new StringBuilder("");
    TimeSpan time = StartTime; // Start/EndTime are `TimeSpan`s defined in another place

    // loop from StartTime to EndTime in 30 min increments
    while(time <= EndTime)
    {
        String t = String.Format(@"{0:hh\:mm}", time);

       try
       {
           var d = GetThisTime(t,data);
           SB.AppendFormat("<option value=\"{0}\">({1}) {0}</option>", t, d["count"]); // error is here: Cannot apply indexing with [] to an expression of type 'object'
       }
       catch
       {
           SB.AppendFormat("<option value=\"{0}\">{0}</option>", t);
       }

        time = time.Add(Length);
    }
    H = SB.ToString();
}
public IEnumerable<dynamic> GetThisTime(String time, IEnumerable<dynamic> data)
{
    return from a in data
           where time.CompareTo(new TimeSpan(a.time)) == 0
           select a;
}

Update: The 'error' I put in comments was not apparent, so I will duplicate here: I get an error at

SB.AppendFormat("<option value=\"{0}\">({1}) {0}</option>", t, d["count"]);

The error is:

Cannot apply indexing with [] to an expression of type 'object'

Since it seems to be unclear: I do not want the count of the IEnumerable, I want the count column of the data set. See the second table above.

12
  • 1
    Does it work? If not, what does it produce? What would you like instead? Commented May 26, 2015 at 11:19
  • GetThisTime return IEnumerable, so it collection, if you want Count of them you need use linq Count method like d.Count() Commented May 26, 2015 at 11:21
  • @LasseV.Karlsen in code comment: // error is here: Cannot apply indexing with [] to an expression of type 'object' Commented May 26, 2015 at 11:24
  • I don't want to count the items in the IEnumerable. I have a count column that I want to get the data from. See the second table from the top. Commented May 26, 2015 at 11:24
  • So this is not actually optimizing something at all, this is about making something compile to begin with? Since you haven't posted what the type of GetThisTime is, it's impossible to know how to provide any help. Have you tried just d.Count ? Commented May 26, 2015 at 11:25

1 Answer 1

1

Now GetThisTime return IEnumerable<dynamic>, so it collection, but you try use it like object. Anyway you need get object first, for example with First or FirstOrDefault and only then try get property value.

You can a bit change your GetThisTime proc, so you not use result except in one place you can simple return count what you need like this

public dynamic GetThisTime(String time, IEnumerable<dynamic> data)
{
    return (from a in data
           where time.CompareTo(new TimeSpan(a.time)) == 0
           select a["count"]).FirstOrDefault();
}

and use it like

SB.AppendFormat("<option value=\"{0}\">({1}) {0}</option>", t, GetThisTime(t,data));

NOTE: your expression seems wrong: you try compare string with TimeSpan

UPDATE: i think you need a bit change your logic like

public void PrepareHTML(dynamic data) 
{
    StringBuilder SB = new StringBuilder("");
    TimeSpan time = StartTime; // Start/EndTime are `TimeSpan`s defined in another place

    // loop from StartTime to EndTime in 30 min increments
    while(time <= EndTime)
    {
        String t = String.Format(@"{0:hh\:mm}", time);
        var d = GetThisTime(t,data); // Send the String instead of TimeSpan
        if(d != null){
           SB.AppendFormat("<option value=\"{0}\">({1}) {0}</option>", t, d); // error is here: Cannot apply indexing with [] to an expression of type 'object'
       }
       else
       {
           SB.AppendFormat("<option value=\"{0}\">{0}</option>", t);
       }

        time = time.Add(Length);
    }
    H = SB.ToString();
}

public object GetThisTime(String time, IEnumerable<dynamic> data)
{
    return (from a in data
           where time == a.time
           select a["count"]).FirstOrDefault();
}
Sign up to request clarification or add additional context in comments.

4 Comments

This fixes the error, but I get a list of all times like this () ##:##. Meaning the number of appointments is empty for each time, even the ones with appointments. It seems like this is bypassing the try catch, and getting an empty result no matter what, whereas it should not even put parenthesis if there are no appointments at that time.
@TravisHeeter, are you see note in answer?
@TravisHeeter, you have a wrong logic in your PrepareHTML why you expect exceptions insted simple check that it times first in interval?
Your Update worked. The only issue was formatting the time as a new TimeSpan in where time = new TimeSpan(a.time): I ended up comparing the Strings instead of TimeSpans. I'll edit your answer to use that instead.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.