tags:

views:

73

answers:

4

when i form the following code

Rabbit[] rbt=
new Rabbit[]
{
   new Rabbit{ Name="Jobby", Vegetable=new Vegetable{ VegiName="carrot"}},
   new Rabbit{ Name="hobby", Vegetable=new Vegetable{ VegiName="Beetroot"}}
};

var s = from bt in rbt where
        bt.Vegetable.VegiName.CompareTo("carrot") == 0 select bt;

foreach (var v in s)
{
                Console.WriteLine("{0}{1}",v.Vegetable.VegiName,v.Name);
}

my query returns single row only, then why do i need foreach iteration ? can't i use

Console.WriteLine("{0}{1}",s.Vegetable.VegiName,s.Name); directly ?
+1  A: 

You can use the Single method to return a single value. Use SingleOrDefault if you suspect it may be null (ie. no results returned).

Rabbit result = s.SingleOrDefault();

if (result != null)
{
    // use result
    Console.WriteLine("{0} : {1}", result.Vegetable.VegiName, result.Name);
}

As others have mentioned, the alternative is to use First or FirstOrDefault to take the first result returned, if the query returns numerous results.

Ahmad Mageed
+6  A: 

How is the compiler meant to know that your query will only return a single row? Suppose you changed your data to include another carrot - or no carrot at all - what would you expect to happen.

If you should definitely get a single result, call Single to get it. If you may get multiple results, call First. If you may get multiple results or none, call FirstOrDefault. If you may get zero or one result, call SingleOrDefault. For example, for the first case:

var s = from bt in rbt where
        bt.Vegetable.VegiName.CompareTo("carrot") == 0 select bt;

var veg = s.Single();

Console.WriteLine("{0}{1}",veg.Vegetable.VegiName,veg.Name);

Or alternatively:

var veg = rbt.Where(bt => bt.Vegetable.VegiName.CompareTo("carrot") == 0)
             .Single();
Console.WriteLine("{0}{1}",veg.Vegetable.VegiName,veg.Name);
Jon Skeet
what is the wrong invar k = from bt in rbt from c in bt.Vegetable where c.VegiName.CompareTo("carrot") == 0 select c; declaration ?
RusselUdana
"from bt in rbt from c in bt.Vegetable" won't work because bt.Vegetable is not IEnumerable. In "from c in ...", the ... has to be IEnumerable.
itowlson
I saw from c in customers, o in c.Orders where o.OrderDate >= new DateTime(1998, 1, 1) select new {c.CustomerID, o.OrderID, o.OrderDate};from microsoft site so i asked.
RusselUdana
In that sample, c.Orders is enumerable (it is that Customer's collection of Orders). In your case, the analogy would be if a Rabbit has a collection of Vegetables -- then the query you were asking about would definitely be appropriate (and necessary).
itowlson
You mean something similar to List<Orders> or other collection right?
RusselUdana
Yes, exactly that (anything that implements IEnumerable<Order> in fact).
itowlson
+1  A: 

No, because LINQ does not know at compile time that s will return only a single row. Use the First() or Single() operator:

var v = (from bt in rbt where
         bt.Vegetable.VegiName.CompareTo("carrot") == 0 
         select bt)
        .First();
itowlson
+2  A: 

Because the type of the query IEnumerable<Rabbit>, not Rabbit. You can get what you want, though, by using a FirstOrDefault() or SingleOrDefault() at the end of your query.

var s = (from bt in rbt
         where bt.Vegetable.VegiName.CompareTo("carrot") == 0
         select bt)
        .FirstOrDefault();
tvanfosson