Question

J'utilise une approche similaire à celle des autres utilisateurs en conservant mes objets LINQ dans mon fournisseur de données LINQ et en renvoyant un IQueryable pour permettre le filtrage, etc. Cela fonctionne très bien pour filtrer un objet simple par son ID ou une autre propriété, mais j'ai un problème avec un objet de la table join qui est composé d'autres objets enfants

    //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 est mon objet Position Linq et je renvoie un poste DTO composé d'un utilisateur, d'un OrgUnit et d'un rôle (la table sous-jacente est une table de jointure avec un ID utilisateur, un IDID et un OrgUnitID)

Le problème que je rencontre est que, lorsque j'essaie d'ajouter un filtre sur Iqueryable, une erreur SQL survient indiquant qu'il n'y a pas de traduction disponible pour mon objet DTO.User

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

Je ne sais vraiment pas comment résoudre ce problème, car tous mes résultats Google semblent concerner des personnes travaillant directement avec les objets LINQ générés

Avez-vous une idée de la façon dont cela fonctionnerait ou est-ce que je fais quelque chose de complètement faux ici?

Merci

Était-ce utile?

La solution 3

J'ai fini par ne pas utiliser de filtres pour mes requêtes complexes. Au lieu de cela, j'ai ajouté des méthodes au référentiel pour les exigences de requête plus complexes. Je pense que cela rendra le système plus facile à comprendre et donc à maintenir.

Autres conseils

J'ai pu travailler avec une approche similaire:

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

Où la carte a:

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

Pourquoi ne pas l'essayer avec ce type d'initialisation (au lieu de constructeurs).

Ps. cela fait partie d'une application fonctionnelle et expiredStatuses est même lié à une expression complexe.

Mise à jour 1: ce scénario est similaire au scénario mentionné, car:

  • La carte renvoie un objet IQueryable, qui est un objet POCO.
  • Après avoir appelé la méthode Map qui renvoie un objet IQueryable avec l'objet POCO, je lui applique un filtre.

Linq2SQL ne comprend que les objets générés par le concepteur. Eh bien, ce n'est pas tout à fait vrai, mais assez proche.

Ainsi, lorsque vous écrivez des requêtes Linq contre des objets Linq2SQL, la requête sera convertie en SQL valide lorsque la requête est réellement exécutée, et non lorsqu'elle est écrite. Puisque vos objets DTO ne sont pas des objets Linq2SQL, Linq2SQL ne saura pas comment créer le code SQL approprié.

Si vous souhaitez conserver votre séparation de cette manière, vous devez trouver un moyen d'exécuter vos requêtes avec uniquement les objets Linq2SQL concernés et de mapper uniquement le résultat sur vos DTO.

Peut-être pourriez-vous réécrire votre méthode de requête pour:

  

Mettre à jour: le paramètre doit être de type.   Expression<>, et il n'y a pas besoin de   renvoyer un IQueryable<>. Grâce à   Freddy pour avoir signalé.

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)
                      };
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top