2008-10-14 9 views
4

Je viens de demander this question. Ce qui m'a conduit à une nouvelle question :)Linq to SQL: .FirstOrDefault() non applicable pour sélectionner un nouveau {...}

Jusqu'à présent, j'ai utilisé le modèle suivant de sélection de choses avec Linq to SQL, dans le but de pouvoir gérer 0 "rows" retourné par la requête:

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

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

Mais je ne peux pas utiliser FirstOrDefault() quand je fais:

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. 

Comment puis-je vérifier 0 « lignes » renvoyées par la requête, en utilisant le second motif?



MISE À JOUR:

Je pense que ma génération échoue parce que je suis en train d'affecter le résultat de la requête à une variable (this._user) déclarée avec le type de [DataContext].User.

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

Erreur de compilation: ne peut pas convertir implicitement le type "AnonymousType # 1" à "[DataContext] .user".

Des idées sur comment je peux contourner cela? Devrais-je faire mon propre objet?

Répondre

1

En ce qui concerne votre UPDATE: vous devez soit créer votre propre type, changer this._user pour être int, soit sélectionner tout l'objet, pas seulement des colonnes spécifiques.

1
if (person.Any()) /* ... */; 

OU

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

Vous pouvez toujours utiliser FirstOrDefault. Il suffit de

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

PersonFields sera nul ou un objet avec les propriétés que vous avez créées.

13

Pourquoi pouvez-vous continuer à faire quelque chose? Est-ce que cela vous donne une erreur?

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

Il est encore un objet de référence comme vous l'objet réel, il est juste anonyme si vous ne connaissez pas le type réel avant que le code est compilé.

+0

D'accord, ce qui précède devrait fonctionner, sauf s'il y a une erreur d'exécution non liée. – Codewerks

+0

Mis à jour ma question. – roosteronacid

2

Mise à jour:

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.

Appel .FirstOrDefault (null) comme ceci:

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

qui fait l'affaire pour moi.