Exposer Entité Cadre de Service WCF
J'ai besoin d'un peu d'aide ici! Je suis en train de créer ma première application à l'aide de Entity Framework, WCF et WPF MVVM technologies. Je suis nouveau à tous. J'ai donc créer un modèle pour ma base de données à l'aide de Entity Framework. Puis-je créer mon service WCF classe. J'ai lu près de 50 articles sur les EF et les services WCF et je suis tout au sujet de la confusion maintenant. Je sais que je ne suis pas censé exposer mon modèle directement. Actuellement, je suis en utilisant ce code en tant que contrat de service:
namespace Ohmio.DataService
{
[ServiceContract]
public class OhmioService
{
[OperationContract]
public IEnumerable<vw_Pedidos> ListarPedidos(string IDComprobante, bool bEntregados, int Numero = -1, int IDCliente = -1)
{
using (var context = new OhmioTestNet())
{
string sqlString="SELECT VALUE cs FROM OhmioTestNet.vw_Pedidos AS cs WHERE cs.ID_Comprobante=='" + IDComprobante + "' AND ";
if (Numero != -1) sqlString += "cs.Numero=="+ Numero.ToString() +" AND ";
if (IDCliente != -1) sqlString += "cs.ID_Cliente=="+ IDCliente.ToString()+" AND ";
if (!bEntregados) sqlString += "cs.Entregado==false AND ";
sqlString =sqlString.Substring(0,sqlString.Length-4);
ObjectQuery<vw_Pedidos> Pedidos = context.CreateQuery<vw_Pedidos>(sqlString);
var result = Pedidos.ToList();
result.ForEach(e => context.Detach(e));
return result;
}
}
[OperationContract]
public IEnumerable<Clientes> GetClientes()
{
using (var context = new OhmioTestNet())
{
var result = context.Clientes.Where(f => f.Activo == true).ToList();
result.ForEach(e => context.Detach(e));
return result;
}
}
}
}
Mes questions:
-
Le problème c'est que ne suppose pas que pour exposer mon modèle de données directement, non? Donc ici, je suis de retour détaché de l'entité de la classe
vw_Pedidos
. Est-ce une mauvaise pratique? -
J'ai lu beaucoup de choses sur DTO et POCO de l'objet, lequel dois-je utiliser à la place le code ci-dessus?
-
Si j'utilise DTO ou POCO pour le transfert de plus de WCF, dois-je le créer manuellement un DTO pour chaque objet de base de données? Dois-je créer manuellement toutes les propriétés (champs) pour chaque id de l'objet?
-
Si j'ajoute un nouveau champ à un objet de base de données et le besoin de le montrer sur le client, puis-je mettre à jour mon modèle EF, ajouter le nouveau champ manuellement à la DTO ou objet POCO? Cela sonne comme un entretien cauchemar!
-
Est à l'aide de EntitiesToDTOs une bonne option pour la création automatique de Dto basé sur EF objets?
-
Puis-je utiliser DTO pour mettre à jour les données dans la base de données?
Désolé pour les multiples questions. S'il vous plaît aidez-moi à sortir d'ici! Je suis à la recherche pour un motif qui m'a conduit à un facile à maintenir, la préoccupation séparés code. Merci!
Mise à JOUR
Suivant TomTom suggestions, j'ai lu beaucoup de choses sur POCOs, EF et Linq to entities. Après que je l'ai ré-écrire mon ensemble de l'application. Je partage mon code sur 5 projets:
1)DataLayer
2)ModelLayer
3)BusinessLyer
4)Service WCF Couche
5)WPF Client
Pour la comunication sur les couches 1 à 5-je utiliser des classes POCO mappé à Entity Framework à l'aide de POCO Modèle T4. Pour communiquer couche 4 et 5 de plus de WCF je veux utiliser une classe personnalisée pour masquer un certain domaine à partir d'un client (je ne veux pas exposer l'ensemble de la classe POCO) donc j'ai ré-écrire la fonction de filtre à l'aide de linq to entities et la projection de IEnumerable:
public IEnumerable<PedidosList> Pedidos_Listar(string sComprobante, Clientes MyCliente = null, DateTime? dDesde = null, DateTime? dHasta = null, bool bCumplidos = false)
{
using (var context = new OhmioEntities())
{
IEnumerable<PedidosList> query =
from Pedidos in context.Pedidos
join Clientes in context.Clientes on Pedidos.ID_Cliente equals Clientes.ID_Cliente
where Pedidos.ID_Comprobante == sComprobante
select new PedidosList {ID_Pedido = Pedidos.ID_Pedido, Fecha=Pedidos.Fecha, Aprobado=Pedidos.Aprobado, Bruto=Pedidos.Bruto, Cliente=Clientes.RazonFantasia,
FechaEntrega=Pedidos.FechaEntrega, Neto=Pedidos.Neto, Numero=Pedidos.Numero, Observaciones=Pedidos.Observaciones, Entregado=Pedidos.Entregado, ID_Cliente=Pedidos.ID_Cliente };
if (MyCliente != null) query = query.Where(i => i.ID_Cliente == MyCliente.ID_Cliente);
if (MyCliente != null) query = query.Where(i => i.ID_Cliente == MyCliente.ID_Cliente);
if (dDesde != null && dHasta != null) query = query.Where(i => i.Fecha >= dDesde && i.Fecha <= dHasta);
if (bCumplidos == false) query = query.Where(i => i.Entregado == false);
return query.ToList();
}
}
Est-ce la meilleure façon de le faire? Puis-je faire la projection APRÈS le filtre? Merci!
- Grand sujet 😉 Pas de réponse en tant que telle, mais je voudrais commencer ici avec cette codeproject.com/Articles/537161/... il explique WCF avec Entity Framework très bien avant de vous déplacer sur MVVM partie
- Merci pour la réponse! J'ai déjà lu cet article et c'est exactement mon point. Dans cet article, un DataContract classe est créée pour Accéder au Produit EF objet et ensuite tous les champs sont mappé à la main un par un entre datacontract classe et EF classe! Cela sonne comme un fou! En fait, vous avez 2 clases avec la même propriété que vous devez manuellement la mise à jour! C'est un entretien nigthmare! N'est-il pas une meilleure façon de le faire?
- Votre mise à jour a l'air bien (même si vous faites de même si et le filtre deux fois dans une rangée, probablement juste une faute de frappe). Personnellement, je ne fais aucun filtrage d'abord, de sorte que vous ne perdez pas de temps CPU pour créer des objets, vous allez juste jeter, mais son seulement une petite optimisation.
- L'article mentionné par @dellywheel dans le premier commentaire a disparu. Une ancienne version de celui-ci est codeproject.com/Articles/127395/... . L'auteur de l'article a aussi un livre packtpub.com/application-development/...
Vous devez vous connecter pour publier un commentaire.
Oui.
À la fois. Étant donné qu'un DTO assez bien, normalement, est un POCO. Peut-être que vous essayez de comprendre ce que les mots SIGNIFIENT. POCO est un "bon Vieux C# de l'Objet" (pas besoin d'hériter d'une classe de base) et c'est tout à fait normal pour un POCO.
Pas. Jamais entendu parler de T4? Qui peuvent être cryptées. Cela dit, ces normalement ne sont pas de base de données, mais les objets de l'API - le service WCF est un (public) avant la fin du programme serveur.
Il est absolument un. Si vous faites les choses sans réfléchir. Sérieusement, une fois que vous avez martelé le modèle de base, ce n'est pas quelque chose qui se passe toutes les 15 minutes. Il comprend également un travail important sur l'extrémité avant et de la logique, de toute façon - je veux dire, si la propriété est inutile alors bon, pourquoi le mettre dans? Si il n'est pas inutile, c'est beaucoup de travail quand même. Et les modèles peuvent être mis à jour, pas besoin de se régénérer.
Diable, j'ai l'habitude de travailler avec des non-trivial de bases de données. Dans ce cas, un changement n'est pas "régénérer un modèle", il comprend aussi des "écrire un sql script de mise à jour pour les versions" et "test de la mise à jour de la performance" (ajout d'un champ à un multi-milliard de lignes de la table avec la valeur par défaut et de générer des indices peut prendre un certain temps). Et il l'est toujours pas de cauchemar, car cela ne se fait pas toutes les 5 minutes. La PLUPART des choses est de ne pas "ajouter des champs", c'est "Programme".
Quoi d'autre?
Vous ne trouverez pas une. C'est une question de faire le bon compromis. Vous NE semblent surestimer la quantité de changements qui se produisent dans un projet.
Vous faire plus de bien à supposer que le service WCF est une limite de confiance et de l'API publique - un peu comme un site web, juste pour la consommation par un ordinateur. Les objets que vous exposez, il ne doit pas absolument conforme à la base de données internes. Il est préférable de générer séparément, et éventuellement les modifier pour être plus en ligne avec ce qui est nécessaire pour l'API publique que pour exposer back-end les détails de l'implémentation d'une API.
Je dois dire, cependant, votre travail est beaucoup plus compliqué par l'archaïsme et absolument contre-productif façon dont vous accédez à la base de données de démarrage à l'aide d'un bon générateur sql et l'objet de mappeur, ou vous aurez un entretien cauchemar là, peu importe comment vous faire le reste. Mettre ensemble des chaînes SQL comme ça, c'est GRAVE "non, jamais". Et de chercher comment l'exposer OData via WCF. Qui vous donne des fonctionnalités de requête via des Url.