Domanda

Sto usando un approccio simile agli altri per mantenere i miei oggetti LINQ nel mio fornitore di dati LINQ e restituire un IQueryable per consentire il filtraggio ecc. Funziona bene per filtrare un oggetto semplice in base al suo ID o altra proprietà, ma sto avendo un problema con un oggetto tabella join composto da altri oggetti figlio

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

Il coreDB.Positions è il mio oggetto Linq Position e sto restituendo una posizione DTO composta da un utente, unità organizzativa e ruolo (la tabella sottostante è una tabella di join con UserID, RoleID e OrgUnitID)

Il problema che sto riscontrando è che quando provo ad aggiungere un filtro sull'Iqueryable ricevo un errore SQL che dice che non c'è traduzione disponibile per il mio oggetto DTO.User

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

Sono totalmente a corto di come risolvere il problema, poiché tutti i miei risultati di Google sembrano essere con persone che lavorano direttamente con gli oggetti LINQ generati

Qualche idea su come farlo funzionare o sto facendo qualcosa di completamente sbagliato qui?

Grazie

È stato utile?

Soluzione 3

Ho finito per non usare i filtri per le mie query complesse. Invece, ho aggiunto metodi al repository per i requisiti di query più complessi. Ritengo che ciò renderà il sistema più semplice da comprendere e quindi da mantenere.

Altri suggerimenti

Sono stato in grado di lavorare con successo con un approccio simile:

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

Dove ha la mappa:

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

Che ne dici di provarlo con quel tipo di inizializzazione (anziché costruttori).

Ps. questo fa parte di un'applicazione funzionante e expiredStatuses è persino correlato a un'espressione complessa.

Aggiornamento 1: Questo è simile rispetto allo scenario menzionato, perché:

  • Map restituisce un oggetto IQueryable, che è un oggetto POCO.
  • Dopo aver chiamato il metodo Map che restituisce un IQueryable con l'oggetto POCO, sto applicando un filtro contro di esso.

Linq2SQL comprende solo gli oggetti generati dal designer. Bene, non è del tutto vero, ma abbastanza vicino.

Pertanto, quando si scrivono nuovamente query Linq su oggetti Linq2SQL, la query verrà convertita in SQL valido quando la query viene effettivamente eseguita, non quando viene scritta. Poiché i tuoi oggetti DTO non sono oggetti Linq2SQL, Linq2SQL non saprà come creare l'SQL corretto.

Se si desidera mantenere la separazione in questo modo, è necessario trovare un modo per eseguire le query con solo gli oggetti Linq2SQL coinvolti e mappare solo il risultato sui DTO.

Forse potresti riscrivere il tuo metodo di query su:

  

Aggiornamento: il parametro deve essere di tipo   Expression<> e non è necessario   restituisce un IQueryable<>. Grazie a   Freddy per averlo segnalato.

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)
                      };
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top