198 votes

Retourne le type anonyme?

À l'aide de l'exemple simple ci-dessous, quelle est la meilleure façon de renvoyer les résultats à partir de plusieurs tables à l'aide de Linq to Sql?

Dire que j'ai deux tables:

Chiens: Nom, Âge, BreedId

Races: BreedId, BreedName

Je veux retourner tous les chiens avec leur BreedName. Je devrais obtenir tous les chiens à l'aide de quelque chose comme ça avec aucun des problèmes:

public IQueryable<Dog> GetDogs()
{
    var db = new DogDataContext(ConnectString);
    var result = from d in db.Dogs
                 join b in db.Breeds on d.BreedId equals b.BreedId
                 select d;
    return result;
}

Mais si je veux des chiens avec des races et essayer ce que j'ai des problèmes:

public IQueryable<Dog> GetDogsWithBreedNames()
{
    var db = new DogDataContext(ConnectString);
    var result = from d in db.Dogs
                 join b in db.Breeds on d.BreedId equals b.BreedId
                 select new
                        {
                            Name = d.Name,
                            BreedName = b.BreedName
                        };
    return result;
}

Maintenant je me rends compte que le compilateur ne me permet pas de renvoyer un ensemble de types anonymes, car il s'attend à des Chiens, mais est-il un moyen de retourner ce, sans avoir à créer un type personnalisé? Ou dois-je créer ma propre classe pour DogsWithBreedNames et de préciser que le type dans le select? Ou est-il un autre moyen plus facile?

Merci à l'avance.

217voto

teedyay Points 10833

J’ai tendance à aller pour ce modèle :

Cela signifie que vous avez une classe supplémentaire, mais il est rapide et facile au code, facilement extensible, réutilisable et de type sécurisé.

69voto

Jon Skeet Points 692016

Vous pouvez retourner les types anonymes, mais ce n'est vraiment pas assez.

Dans ce cas, je pense qu'il serait de loin préférable de créer le type approprié. Si c'est uniquement destiné à être utilisé dans le type de contenant la méthode, d'en faire un type imbriqué.

Personnellement, j'aimerais C# pour obtenir "le nom des types anonymes" - c'est à dire le même comportement que les types anonymes, mais avec les noms et les déclarations de propriété, mais c'est tout.

EDIT: d'Autres sont en suggérant le retour des chiens, puis en accédant à la race nom par l'intermédiaire d'un chemin de la propriété, etc. C'est parfaitement raisonnable, mais IME il conduit à des situations où vous avez fait une requête en particulier parce que les données que vous souhaitez utiliser - et que les méta-informations sont perdues lorsque vous venez de revenir IEnumerable<Dog> - la requête peut être attend de vous à utiliser (dire) Breed plutôt que d' Owneren raison de certaines options de chargement etc, mais si vous oubliez que vous avez et de commencer à utiliser d'autres propriétés, votre application peut fonctionner, mais pas aussi efficacement que vous auriez été envisagé à l'origine. Bien sûr, je pourrais en parler des ordures, ou de la sur-optimisation, etc...

17voto

Peter Perháč Points 8007

Juste pour ajouter mon grain de sel :-) J'ai récemment appris une façon de les manipuler des objets anonymes. Il ne peut être utilisé lorsque le ciblage de la .NET 4 cadre et que seulement lors de l'ajout d'une référence à System.Web.dll mais alors c'est très simple:

...
using System.Web.Routing;
...

class Program
{
    static void Main(string[] args)
    {

        object anonymous = CallMethodThatReturnsObjectOfAnonymousType();
        //WHAT DO I DO WITH THIS?
        //I know! I'll use a RouteValueDictionary from System.Web.dll
        RouteValueDictionary rvd = new RouteValueDictionary(anonymous);
        Console.WriteLine("Hello, my name is {0} and I am a {1}", rvd["Name"], rvd["Occupation"]);
    }

    private static object CallMethodThatReturnsObjectOfAnonymousType()
    {
        return new { Id = 1, Name = "Peter Perhac", Occupation = "Software Developer" };
    }
}

Afin d'être en mesure d'ajouter une référence à System.Web.dll vous aurez à suivre rushonerok conseils : assurez-vous que votre [du projet] framework cible est ".NET Framework 4" non ".NET Framework 4 Client Profile".

8voto

joshperry Points 17727

Non vous ne peut pas retourner des types anonymes sans passer par une ruse.

Si vous n’avez pas utilisé c#, ce qui vous aurait être recherché (renvoi des données multiples sans un type concret) est appelé un Tuple.

Il y a beaucoup de c# tuple mises en œuvre, à l’aide de l' un, montré ici, votre code pourrait fonctionner comme cela.

Et sur le site d’appel :

8voto

tjscience Points 1232

Vous pourriez faire quelque chose comme ceci:

 
public System.Collections.IEnumerable GetDogsWithBreedNames()
{
    var db = new DogDataContext(ConnectString);
    var result = from d in db.Dogs
                 join b in db.Breeds on d.BreedId equals b.BreedId
                 select new
                        {
                            Name = d.Name,
                            BreedName = b.BreedName
                        };
    return result.ToList();
}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X