Linq To SQL OrderBy, проблема при использовании перечислений - PullRequest
6 голосов
/ 18 декабря 2008

У меня возникли проблемы с использованием метода расширения OrderBy в запросе LINQ, когда он работает с типом enum. Я создал обычный DataContext с использованием Visual Studio, просто перетаскивая все на дизайнера. Затем я создал отдельные модели сущностей, которые являются просто POCO, и я использовал шаблон хранилища для извлечения данных из моей базы данных и сопоставления их с моими собственными моделями сущностей (точнее, у меня есть шаблон хранилища, который накапливается и IQueryable это все сделает).

Все работает просто отлично, за исключением случаев, когда я пытаюсь применить OrderBy (вне репозитория) к свойству, которое я сопоставил от short / smallint для перечисления.

Вот соответствующие биты кода:

public class Campaign
{
    public long Id { get; set; }
    public string Name { get; set; }
    ....
    public CampaignStatus Status { get; set; }
    ...
}
public enum CampaignStatus : short {
    Active,
    Inactive,
    Todo,
    Hidden
}
public class SqlCampaignRepository : ICampaignRepository
{
...
    public IQueryable<Campaign> Campaigns()
    {
        DataContext db = new DataContext();
        return from c in db.Campaigns
                select new Campaign
                   {
                       Id = c.Id,
                       Name = c.Name,
                       ...
                       Status = (CampaignStatus)c.Status,
                       ...
                   };
     }
}

А потом в другом месте

SqlCampaignRepository rep = new SqlCampaignRepository();
var query = rep.Campaigns().OrderBy(c => c.Status);

Это вызывает следующее исключение: System.ArgumentException не был обработан кодом пользователя Сообщение = «Аргумент« значение »был неправильного типа. Ожидаемый« IQMedia.Models.CampaignType ». Фактический« System.Int16 »." Источник = "System.Data.Linq" Трассировки стека: ved System.Data.Linq.SqlClient.SqlOrderExpression.set_Expression (значение SqlExpression) ved System.Data.Linq.SqlClient.SqlBinder.Visitor.VisitSelect (SqlSelect select) ved System.Data.Linq.SqlClient.SqlVisitor.Visit (узел SqlNode) ved System.Data.Linq.SqlClient.SqlBinder.Visitor.VisitIncludeScope (область действия SqlIncludeScope) ...

(извините за датский язык, ved = by / at).

Я попытался вписать Status в short в выражении orderBy, но это не поможет, если я приведу его к фактическому типу enum.

Любая помощь, исправляющая это, очень ценится!

Ответы [ 3 ]

3 голосов
/ 18 декабря 2008

Можете ли вы указать тип CampaignStatus непосредственно в вашем DataContext через дизайнер? Таким образом, значение автоматически сопоставляется с enum.

1 голос
/ 18 декабря 2008

Какая связь между классом Campaign и Campaigns? Если Campaigns возвращает набор объекта Campaign, учтите, что вы не можете select new отображать объект.

Интересно, будет ли работать лучше, если вы сделали OrderBy до выбора?

Один последний трюк может состоять в создании поддельной композиции [Function], используя тривиальный TSQL. Например, ABS может быть достаточно. то есть что-то вроде (в контексте):

    [Function(Name="ABS", IsComposable=true)] 
    public int Abs(int value) 
    { // to prove not used by our C# code... 
        throw new NotImplementedException(); 
    }

Тогда попробуйте:

  .OrderBy(x => ctx.Abs(x.Status))

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

Стоит выстрел ...

0 голосов
/ 18 декабря 2008

Мой DataContext имеет свой собственный класс сущностей с именем Campaign (конечно, в другом пространстве имен). Кроме того, столбец состояния сохраняется в базе данных как smallint, а для пространства имен LINQ Entity его тип указан как короткий (System.Int16).

Порядок действует, если я применяю его в запросе в моем хранилище - хотя это все часть большего, и вся идея в том, чтобы хранилище НЕ применялось какой-либо сортировки, фильтрации или чего-либо подобного, но просто сопоставьте классы сущностей базы данных с моими собственными. Этот пример, очевидно, является немного бессмысленным, в котором это в значительной степени прямое отображение, но в некоторых случаях я также добавил в него локализацию.

Также я забыл добавить - исключение, очевидно, не происходит, пока я не попытаюсь выполнить запрос (т. Е. - вызов ToList или перечисление по коллекции).

В общих чертах этот метод используется классом обслуживания, который затем должен добавить фильтрацию, сортировку и все такое - и смысл всего этого, конечно, состоит в том, чтобы немного отделить вещи, но также позволить легко переход к другой базе данных или к другому ИЛИ / М, позже, если это будет желанием.

Ах, я не видел этот последний бит до того, как я ответил - у меня еще не было опыта использования атрибута Function, но у меня не будет доступа к тексту данных в классе, где я должен применить сортировку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...