Pergunta

Eu estou usando uma abordagem semelhante para os outros em manter meus objetos LINQ no meu provedor de dados LINQ e retornando um IQueryable para permitir filtragem etc. Esta multa trabalha para filtrar um simples objeto por ele é ID ou outra propriedade, mas eu estou tendo um problema com a juntar-se objeto de tabela que é composta de outros objetos filho

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

Os coreDB.Positions é meu objeto Linq posição e estou retornando uma posição DTO que é composto de um usuário, unidade organizacional e Papel (tabela subjacente é uma junção mesa com UserID, RoleID e OrgUnitID)

O problema que estou tendo é que quando eu tento adicionar um filtro no IQueryable recebo um erro de SQL dizendo que não há tradução disponível para o meu objeto DTO.User

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

Eu estou em uma perda completa de como proceder para resolver isso, como todos os meus resultados do Google parecem estar com as pessoas que trabalham diretamente com os objetos LINQ gerados

Qualquer pensamento a respeito de como fazer este trabalho, ou estou fazendo algo completamente errado aqui?

Graças

Foi útil?

Solução 3

acabei não usando filtros para minhas consultas complexas. Em vez disso, eu adicionei métodos para o repositório para os requisitos de consulta mais complexos. Eu sinto isso vai tornar o sistema mais fácil de entender e, portanto, manter.

Outras dicas

Eu tenho sido capaz de trabalhar com sucesso com uma abordagem semelhante:

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

Onde Mapa tem:

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

Que tal experimentar com esse tipo de inicialização (em vez de construtores).

Ps. isso é parte de um aplicativo de trabalho, e os expiredStatuses sequer é relacionado a uma expressão complexa.

Update 1: Isto é similar em comparação com o cenário mencionado, porque:

  • Mapa está retornando um IQueryable, que é um objeto POCO.
  • Depois de chamar o método Mapa que retorna um IQueryable com o objeto POCO Estou aplicando um filtro contra ela.

Linq2SQL só compreender os objetos gerados pelo designer. Bem, isso não é inteiramente verdade, mas perto o suficiente.

Assim, quando você escrever consultas LINQ agains Linq2SQL objetos, a consulta será convertida para SQL válida quando a consulta é realmente executada, não quando ele é escrito. Desde seus objetos DTO não são Linq2SQL objetos, Linq2SQL não vai saber como criar o SQL adequada.

Se você quer manter sua separação desta maneira, você tem que encontrar uma maneira de executar suas consultas com apenas Linq2SQL objetos envolvidos e somente mapear o resultado para seus DTOs.

Talvez você poderia reescrever o método de consulta para:

Update: O parâmetro deve ser do tipo Expression<>, e não há necessidade de retornar um IQueryable<>. Graças a Freddy por apontar.

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)
                      };
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top