Linq to SQL DTO и составные объекты - PullRequest
4 голосов
/ 04 марта 2009

Я использую аналогичный подход к другим в сохранении моих объектов LINQ в моем поставщике данных LINQ и возвращении IQueryable, чтобы разрешить фильтрацию и т. Д. Это прекрасно работает для фильтрации простого объекта по его идентификатору или другому свойству, но у меня есть проблема с объектом таблицы соединений, который состоит из других дочерних объектов

    //CoreDBDataContext db = coreDB;
public IQueryable<DTO.Position> GetPositions()    {
     return from p in coreDB.Positions
         select new DTO.Position
             {
             DTO.User = new DTO.User(p.User.id,p.User.username, p.User.firstName,p.User.lastName,p.User.email,p.User.isActive),
             DTO.Role = new DTO.Role(p.Role.id, p.Role.name, p.Role.isActive),
             DTO.OrgUnit = new DTO.OrgUnit(p.OrgUnit.id,p.OrgUnit.name,p.OrgUnit.isActive)
             };

coreDB.Positions - это мой объект позиции Linq, и я возвращаю позицию DTO, которая состоит из пользователя, OrgUnit и роли (базовая таблица является таблицей соединений с UserID, RoleID и OrgUnitID)

Проблема, с которой я сталкиваюсь, заключается в том, что, когда я пытаюсь добавить фильтр в Iqueryable, я получаю сообщение об ошибке SQL, в котором говорится, что для моего объекта DTO.User нет перевода

public static IQueryable<Position> WithUserID(this IQueryable<Position> query, int userID)
    {
        return query.Where(p => p.User.ID == userID);
    }

Я в полной растерянности относительно того, как решить эту проблему, поскольку все мои результаты в Google, похоже, относятся к людям, работающим непосредственно с сгенерированными объектами LINQ

Есть мысли о том, как заставить это работать, или я делаю что-то совершенно не так?

Спасибо

Ответы [ 3 ]

1 голос
/ 04 марта 2009

Мне удалось успешно работать с подобным подходом:

var courses = from c in Map(origCourses)
where !expiredStatuses.Contains(c.Status)
select c;

Где на карте есть:

    select new UserCourseListItem
    {
        CourseID = c.CourseID,
        CourseName = cm.CourseName,
        CourseType = c.CourseType.Value
        ...

Как насчет того, чтобы попробовать это с этим типом инициализации (вместо конструкторов).

Ps. это часть рабочего приложения, а expiredStatuses даже связан со сложным выражением.

Обновление 1: Это похоже на упомянутый сценарий, потому что:

  • Карта возвращает IQueryable, который является объектом POCO.
  • После вызова метода Map, который возвращает IQueryable с объектом POCO, я применяю фильтр к нему.
1 голос
/ 09 марта 2009

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

1 голос
/ 04 марта 2009

Linq2SQL понимает только объекты, созданные дизайнером. Ну, это не совсем так, но достаточно близко.

Таким образом, когда вы пишете запросы Linq снова против объектов Linq2SQL, запрос будет преобразован в действительный SQL, когда запрос фактически выполняется, а не когда он написан. Поскольку ваши DTO-объекты не являются объектами Linq2SQL, Linq2SQL не будет знать, как создать правильный SQL.

Если вы хотите сохранить разделение таким образом, вам нужно найти способ выполнить ваши запросы только с задействованными объектами Linq2SQL и сопоставить результат только с вашими DTO.

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

Обновление: Параметр должен быть типа Expression<>, и нет необходимости вернуть IQueryable<>. Благодаря Фредди за указание.

public IEnumerable<DTO.Position> FindPositions(Expression<Func<Position, bool>> criteria)
{
    return from p in coreDB.Positions
           where criteria.Invoke(p)
           select new DTO.Position
                      {
                          User = new DTO.User(p.User.id, p.User.username, p.User.firstName, p.User.lastName,
                                       p.User.email, p.User.isActive),
                          Role = new DTO.Role(p.Role.id, p.Role.name, p.Role.isActive),
                          OrgUnit = new DTO.OrgUnit(p.OrgUnit.id, p.OrgUnit.name, p.OrgUnit.isActive)
                      };
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...