tags:

views:

463

answers:

2

Hello Friends,

I am a beginner with LINQ and lambda function's. I was wondering how can i convert multiple linq statement to one statement using selectmany function.

string viewname = (from a in StoredProcedureParameters.Tables[0].AsEnumerable()
                 where a.Field<string>("ViewName") == displayName
                 select a.Field<string>("View")).Single();

DateTime date = (from d in StoredProcedureParameters.Tables[0].AsEnumerable()
                select d.Field<DateTime>("Date")).First();

Thanks for help in advance.

A: 

I don't think SelectMany does what you think it does. It's usually just a flatten operation. Why do you think it would help you in this case? Why do you want to avoid two queries?

Jon Skeet
Hi Jon,So the other time i could write something like this var files = Directory.GetFiles(@"C:\"). Where(f => f.Equals(@"C:\BcBtRmv.log")). SelectMany(i => i, (j, n) => new { j, n }).FirstOrDefault();now further i can do something like files.j , files.n .But in the above query, as described in the question i am not able to return the anonymous type with anonymous values. Hence i was wondering how can i write the above 2 statements so that i dont need to create any new class or anything and get the values of the anonymous type.
netmatrix01
@AG: The problem is that you've got two very different queries: one's got a "where" clause and you're calling Single; the other has no "where" clause but uses "First". Basically it's not conducive to being a single query.
Jon Skeet
Hi Jon,Thanks for your help earlier. I understand your point now as both the queries are very different. I really appreciate you helping us people with understanding more of Functional aspect of C#
netmatrix01
+3  A: 

If you want a single query, you could have the select value be an anonymous type. But the scope of the return value is the method where the type is created.

var result = (from a in StoredProcedureParameters.Tables[0].AsEnumerable()
                 where a.Field<string>("ViewName") == displayName
                 select new { View = a.Field<string>("View"),
                              Date = d.Field<DateTime>("Date") }).Single();

then the variable result will be an object with the properties 'View' and 'Date'. You can't return this value from a method though. If you need to return the value, you could create a simple class

public class ViewDate
{
  public string View { get; set; }
  public DateTime Date { get; set; }
}

Then using an object initializer, you will end up with result containing an instance of the ViewDate object, which you can return from your method.

var result = (from a in StoredProcedureParameters.Tables[0].AsEnumerable()
                 where a.Field<string>("ViewName") == displayName
                 select new ViewDate() { View = a.Field<string>("View"),
                              Date = d.Field<DateTime>("Date") }).Single();
NerdFury
That doesn't give the same results as the original queries - because there's no "where" clause in the original second query.
Jon Skeet
I don't claim to know what he is doing with his queries. A scenario where you want the date from the first record, and the string result from a different record has a funny smell to it.
NerdFury
I agree, it's odd... but my point is that your answer *doesn't* convert the original code into a single query.
Jon Skeet
I don't disagree that I didn't answer the question exactly. And I see your point that I should probably be more true to the code written, but I can't help but feel that the behavior of the code and the intent of the code are not the same in this case (ie. it's a bug). His admission of being new to linq means he might have been caught up in syntax, over correct functionality. It's an assumption I maybe shouldn't make. I was going to let AG expand on his question if he didn't like our answers. But your rep is 102K above mine, so I shouldn't question the guy that can divide by 0 ;)
NerdFury