Linq para SQL: .FirstOrDefault () não aplicável para selecionar novo {...}

Acabei de fazer uma esta pergunta . O que me leva a uma nova pergunta :)

Até este ponto, eu usei o seguinte padrão de seleção de coisas com o Linq para SQL, com o propósito de ser capaz de manipular 0 "linhas" retornadas pela consulta:

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

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

Mas eu não posso usar FirstOrDefault() quando eu faço:

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:

Acho que minha compilação falha porque estou tentando atribuir o resultado da consulta a uma variável ( this._user ) declarada com o tipo de [DataContext] .User .

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

Erro de compilação: não é possível converter implicitamente o tipo "AnonymousType # 1" para "[DataContext] .User".

Alguma idéia de como eu posso contornar isso? Eu teria que fazer meu próprio objeto?

4

5 Respostas

Por que você pode continuar fazendo o mesmo? Está lhe dando um erro?

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.
}

Ainda é um objeto de referência como se fosse um objeto real, é apenas anônimo, portanto você não sabe o tipo real antes que o código seja compilado.

13
adicionado
Atualizei minha pergunta.
adicionado o autor roosteronacid, fonte
De acordo, o acima deve funcionar, a menos que haja um erro de execução não relacionado.
adicionado o autor Codewerks, fonte

Atualização:

Eu vejo agora o que você estava realmente perguntando! Desculpe, minha resposta não se aplica mais. Eu pensei que você não estava recebendo um valor nulo quando estava vazio. A resposta aceita está correta, se você quiser usar o objeto fora do escopo, você precisa criar um novo tipo e apenas usar New MyType (...). Eu sei que o RefactorPro do DevEx tem uma refatoração para isso, e acho que o resharper também funciona.

Chame .FirstOrDefault (null) assim:

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);

Isso faz o truque para mim.

2
adicionado
if (person.Any()) /* ... */;

OU

if (person.Count() == 0) /* ... */;
1
adicionado

Em relação ao seu UPDATE: você tem que criar seu próprio tipo, alterar this._user para ser int , ou selecionar o objeto inteiro, não apenas colunas específicas.

1
adicionado

Você ainda pode usar FirstOrDefault . Só tem

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

PersonFields será nulo ou um objeto com as propriedades que você criou.

0
adicionado