5

I just asked this question. Which lead me to a new question :)

Up until this point, I have used the following pattern of selecting stuff with Linq to SQL, with the purpose of being able to handle 0 "rows" returned by the query:

var person = (from p in [DataContextObject].Persons
              where p.PersonsID == 1
              select new p).FirstOrDefault();

if (person == null)
{
    // handle 0 "rows" returned.
}

But I can't use FirstOrDefault() when I do:

var person = from p in [DataContextObject].Persons
             where p.PersonsID == 1
             select new { p.PersonsID, p.PersonsAdress, p.PersonsZipcode };

// Under the hood, this pattern generates a query which selects specific
// columns which will be faster than selecting all columns as the above
// snippet of code does. This results in a performance-boost on large tables.

How do I check for 0 "rows" returned by the query, using the second pattern?



UPDATE:

I think my build fails because I am trying to assign the result of the query to a variable (this._user) declared with the type of [DataContext].User.

this._user = (from u in [DataContextObject].Users
              where u.UsersID == [Int32]
              select new { u.UsersID }).FirstOrDefault();

Compilation error: Cannot implicitly convert type "AnonymousType#1" to "[DataContext].User".

Any thoughts on how I can get around this? Would I have to make my own object?

Community
  • 1
  • 1
cllpse
  • 21,396
  • 37
  • 131
  • 170

5 Answers5

13

Why can you keep doing the samething? Is it giving you an error?

var person = (from p in [DataContextObject].Persons
              where p.PersonsID == 1
              select new { p.PersonsID, p.PersonsAdress, p.PersonsZipcode }).FirstOrDefault();

if (person == null) {    
    // handle 0 "rows" returned.
}

It is still a reference object just like you actual object, it is just anonymous so you don't know the actual type before the code is compiled.

Nick Berardi
  • 54,393
  • 15
  • 113
  • 135
2

Update:

I see now what you were actually asking! Sorry, my answer no longer applies. I thought you were not getting a null value when it was empty. The accepted response is correct, if you want to use the object out of scope, you need to create a new type and just use New MyType(...). I know DevEx's RefactorPro has a refactoring for this, and I think resharper does as well.

Call .FirstOrDefault(null) like this:

string[] names = { "jim", "jane", "joe", "john", "jeremy", "jebus" };
var person = (
    from p in names where p.StartsWith("notpresent") select 
        new { Name=p, FirstLetter=p.Substring(0,1) } 
    )
    .DefaultIfEmpty(null)
    .FirstOrDefault();

MessageBox.Show(person==null?"person was null":person.Name + "/" + person.FirstLetter);

That does the trick for me.

Andrew
  • 8,322
  • 2
  • 47
  • 70
1
if (person.Any()) /* ... */;

OR

if (person.Count() == 0) /* ... */;
Mark Cidade
  • 98,437
  • 31
  • 224
  • 236
1

Regarding your UPDATE: you have to either create your own type, change this._user to be int, or select the whole object, not only specific columns.

liggett78
  • 11,260
  • 2
  • 29
  • 29
0

You can still use FirstOrDefault. Just have

var PersonFields = (...).FirstOrDefault()  

PersonFields will be be null or an object with those properties you created.

slavoo
  • 5,798
  • 64
  • 37
  • 39
Peter
  • 3,563
  • 5
  • 30
  • 43