Как Вы возвращаете значение по умолчанию, если LINQ к запросу объектов не возвращает значений

LSP касается инвариантов.

классический пример дан следующим объявлением псевдокода (опущенные реализации):

class Rectangle {
    int getHeight()
    void setHeight(int value)
    int getWidth()
    void setWidth(int value)
}

class Square : Rectangle { }

Теперь у нас есть проблема, хотя интерфейс соответствует. Причина состоит в том, что мы нарушили инварианты, происходящие от математического определения квадратов и прямоугольников. Путем методы get и работа методов set, Rectangle должны удовлетворить следующий инвариант:

void invariant(Rectangle r) {
    r.setHeight(200)
    r.setWidth(100)
    assert(r.getHeight() == 200 and r.getWidth() == 100)
}

Однако этот инвариант должен быть нарушенным корректной реализацией Square, поэтому это не допустимая замена Rectangle.

11
задан Stuart Helwig 16 May 2011 в 06:06
поделиться

5 ответов

В итоге я выбрал очень простой подход, который был рекомендован в ответе, который был удален позже:

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);
}
1
ответ дан 3 December 2019 в 03:19
поделиться

Просто добавьте значение по умолчанию перед получением первого элемента.

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

Обратите внимание, что теперь вы можете безопасно использовать First () вместо FirstOrDefault () .

UPDATE

] LINQ to Entity не распознает метод расширения DefaultIfEmpty () . Но вы можете просто использовать нулевой оператор объединения.

var vote = db.Vote.FirstOrDefault(v => v.Voter.Id == user.Id) ?? defaultVote;
4
ответ дан 3 December 2019 в 03:19
поделиться

Добавьте собственный метод расширения . Например:

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

С этим классом в области видимости вы можете сказать:

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

Конечно, ваш метод также может иметь перегрузку, которая возвращает значение по умолчанию (T), если это было то, что вы искали. Во встроенном классе Extension уже определен метод расширения DefaultIfEmpty, поэтому я назвал этот метод в примере «FirstOrDefault», что мне кажется более подходящим.

5
ответ дан 3 December 2019 в 03:19
поделиться

Другой подход, если Vote является ссылочным типом и, таким образом, использует null в качестве значения по умолчанию, будет использовать оператор объединения с нулевым значением:

var vote = (db.Vote
   .Where(v => v.Voter.Id == user.Id)
   .FirstOrDefault()) ?? defaultVote;
18
ответ дан 3 December 2019 в 03:19
поделиться

По какой-то причине, если я превращаю набор результатов в список, Defaultifempty () работает, я не знаю, случайно ли я перешел в область Linq.

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();
0
ответ дан 3 December 2019 в 03:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: