views:

1581

answers:

5

In a LINQ to entities expression like this:

var vote = (from vote in db.Vote where
    vote.Voter.Id == user.Id
    select v).FirstOrDefault();

how do you you add a DefaultIfEmpty so that when there's no vote I'd get a default value?

A: 

Add your own extension method. For instance:

public static class Extension
{
    public static T FirstOrDefault(this IEnumerable<T> sequence, T defaultValue)
    { 
        return sequence.Any() ? sequence.First() : defaultValue;
    }
}

With that class in scope, you can say:

var vote = (from vote in db.Vote where
    vote.Voter.Id == user.Id
    select v).FirstOrDefault(yourDefaultValue);

Of course, your method can also have an overload that returns default(T), if that was what you where looking for. There is already defined a DefaultIfEmpty extension method in the built-in Extension class, so I named the method in the example "FirstOrDefault", which seems like a better fit.

driis
DefaultIfEmpty() already exists as an extension method :)http://msdn.microsoft.com/en-us/library/bb355419.aspx
Steve Guidi
You're right, I edited the example to use a better name.
driis
Why should I re-write a FirstOrDefault when there's already one designed for that purpose?
J. Pablo Fernández
Did you not want to be able to select another value than default ? Or am I missing something ?
driis
No, I just want to use the preovided methods, not re-implement them.
J. Pablo Fernández
A: 

Just add the default value before getting the first element.

var vote = db.Vote
    .Where(v => v.Voter.Id == user.Id)
    .DefaultIfEmpty(defaultVote)
    .First();

Note that you can now safely use First() instead of FirstOrDefault().

UPDATE

LINQ to Entity does not recognize the DefaultIfEmpty() extension method. But you can just use the null coalescing operator.

var vote = db.Vote.FirstOrDefault(v => v.Voter.Id == user.Id) ?? defaultVote;
Daniel Brückner
If when adding a default you can use First, why does FirstOrDefault exists at all?
J. Pablo Fernández
Many of the LINQ operators are somewhat redundant - sequence.Any() can be rewritten as sequence.Count() > 0. You can use sequence.Where(item => Condition(item)).First() or sequence.First(item => Condition(item)). You can use joins or nested queries. When writing code you can use for, do, and while loops. You can even use goto. Usually there is not just one way to achieve a given goal.
Daniel Brückner
Note that seq.Count() (for objects that don't implement ICollection) will enumerate the full sequence while seq.Any() will return as soon as an element is found. Similar, but different. :)
dahlbyk
Of course, the count solution might be much slower. I just wanted to point out that there are usually quite a few ways to achieve a goal.
Daniel Brückner
+2  A: 

Another approach, if Vote is a reference type and thus uses null as its default value, would be to use the null coalescing operator:

var vote = (db.Vote
   .Where(v => v.Voter.Id == user.Id)
   .FirstOrDefault()) ?? defaultVote;
Robert Rossney
A: 

I ended up going for a very simple approach which was recommended by an answer here that was latter erased:

var vote = (from vote in db.Vote 
            where vote.Voter.Id == user.Id
            select v).FirstOrDefault();
if (vote == null) {
    vote = new Vote() { .... };
    db.AddToVoteSet(vote);
}
J. Pablo Fernández
A: 

For some reason if I turn the resultset into a List, the Defaultifempty() works I don't know if I've inadvertantly crossed over into Linq area.

var results = (from u in rv.tbl_user
                        .Include("tbl_pics")
                        .Include("tbl_area")
                        .Include("tbl_province")
                        .ToList()
                        where u.tbl_province.idtbl_Province == prov
                       select new { u.firstName, u.cellNumber, u.tbl_area.Area, u.ID, u.tbl_province.Province_desc,
                                    pic = (from p3 in u.tbl_pics
                                           where p3.tbl_user.ID == u.ID
                                           select p3.pic_path).DefaultIfEmpty("defaultpic.jpg").First()
                                               }).ToList();
Rand