Wilfried Woivré & .Net

Entity Framework : LoadProperty, des erreurs à éviter !

MARS9

La fonction LoadProperty dans Entity Framework vous permet de charger les différentes propriétés d’une entité selon les conditions de navigations qui sont définies dans le Model.

Pour voir ce que vous pouvez réaliser avec cette méthode, je ne peux que vous conseiller que de consulter MSDN !

 

Bon c’est bien beau, mais parfois vous pouvez avoir différents bugs, je vais donc vous en montrer deux avec les différents messages d’erreurs associés. Prenons donc le code suivant, basé sur Northwind, il compile correctement.

var entities = new NorthwindEntities();
var result = entities.Region;
foreach (var item in result)
    entities.LoadProperty(item, "Territory");

foreach (var item in result)
{
    Console.WriteLine(String.Format("Region : {0}, nb de territoires {1}",
        item.RegionDescription.Trim(),
        item.Territories.Count));
}
 

On a donc une première erreur à l’exécution

image
 

Bon le message de l’erreur est clair, il faut mettre la propriété de navigation qui est “Territories” et non “Territory”, il vous faut donc faire attention, puisque contrairement aux requêtes Linq, ici, on se base sur des chaines de caractères et donc susceptibles aux erreurs.

 

Bon maintenant qu’on a corrigé cela, passons à la deuxième erreur que nous affiche gentiment Visual Studio

 

image

 

Bon cette erreur est déjà un peu moins explicite que la précédente, si l’on regarde le message de l’InnerException, on peut voir ce message d’erreur

“There is already an open DataReader associated with this Command which must be closed first.”

Donc après quelques recherches non fructueuses, le problème vient de la chaine de connexion généré par l’utilitaire Entity Framework qui a indiqué ceci :

    <add name="NorthwindEntities" 
         connectionString="metadata=res://*/NWModel.csdl|res://*/NWModel.ssdl|res://*/NWModel.msl;
         provider=System.Data.SqlClient;
         provider connection string=&quot;
         Data Source=.\SQLEXPRESS;Initial Catalog=Northwind;
         Integrated Security=True;MultipleActiveResultSets=False&quot;" 
         providerName="System.Data.EntityClient" />

 

Bien qu’elle a l’air correct (et d’ailleurs, elle l’est), elle ne permet pas d’effectuer deux requêtes en même temps par connexion à cause de la propriétés MultipleActiveResultSets qui est à false, il vous suffit donc de le mettre à true, et le tour est joué !

 

Bon ce cas m’est arrivé avec une connexion à une base SQL Azure, puisque sinon il me génère correctement la chaine de connexion pour autoriser le LoadProperty.

 

Voilà en espérant que ça vous soit utile à vous aussi !

Remonter

WCF RIA Services et les Complex Type d’Entity Framework

MAI1

Actuellement, je suis en train de réaliser un projet pour une formation Silverlight, le but de ce projet est de réaliser un mini site eCommerce totalement en Silverlight. Il s’articule autour des technologies Entity Framework et RIA Services ainsi que Silverlight 4 avec un design pattern de type MVVM. J’utilise comme base de données AdventureWorksLT2008. Je donnerais tout le code de cette démonstration sur mon blog un autre jour, avec une explication un peu plus conséquente !

Enfin passons, pour ma vie, dans cet article je vais vous montrer comment renvoyer un Complex Type crée depuis EntityFramework et renvoyer dans notre Silverlight.

Je commence donc par créer un projet de type Silverlight Business Application, ensuite je crée un modèle Entity Framework, ici, on se basera uniquement sur la table Employees de NorthWind.

Sur cette table, je vais vouloir récupérer uniquement les noms et les prénoms des employés, afin de les renvoyer à mon application Silverlight, je vais donc créer un ComplexType contenant deux chaines de caractères.

J’en suis donc arrivé à un diagramme ressemblant à ceci :

image

Maintenant créons notre Domain Service, et notre requête Linq qui ressemble à cela :

[EnableClientAccess()]
public class NortwindDomainService : LinqToEntitiesDomainService<NorthwindEntities>
{

// TODO: Consider
// 1. Adding parameters to this method and constraining returned results, and/or
// 2. Adding query methods taking different parameters.
public IQueryable<EmployeeInformation> GetEmployees()
{
return from e in ObjectContext.Employees
select new EmployeeInformation() { FirstName = e.FirstName, LastName = e.LastName };
}
}

On s’apprête donc à créer une interface pour afficher les données en Silverlight, sauf qu’en compilant on obtient une erreur :

image

Il manque donc une clef à notre complex type, qu’à cela ne tienne, pour en rajouter une, il suffit de créer une classe partielle à notre type et d’y ajouter une clé.

public partial class EmployeeInformation
{
[Key]
[DataMember]
public int EmployeeInformationId { get; set; }
}

Maintenant que ce problème est réglé et qu’on a bien entendu ajouter la déclaration de notre clé dans notre requête, il faut passer au front, on va donc créer un liste qui affiche les noms et les prénoms des employés

On obtient un code de ce style :

public IEnumerable<Entity> Employees
{
get { return (IEnumerable<Entity>)GetValue(EmployeesProperty); }
set { SetValue(EmployeesProperty, value); }
}

// Using a DependencyProperty as the backing store for Employees.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty EmployeesProperty =
DependencyProperty.Register("Employees", typeof(IEnumerable<Entity>), typeof(MainPage), new PropertyMetadata(null));

public MainPage()
{
InitializeComponent();
this.DataContext = this;
this.Loaded += (sender, e) => LoadData();
}

private void LoadData()
{
NortwindDomainContext context = new NortwindDomainContext();
LoadOperation loadOp = context.Load(context.GetEmployeesQuery());
Employees = loadOp.Entities;
}

On charge donc le tout dans une liste que l’on expose à notre interface, le tout compile sans aucun problème on s’attend donc à voir un résultat, cependant on obtient encore une erreur :

image

On a donc une exception au niveau de notre DomainService, la requête quand à elle est bonne, le seul problème est en fait une erreur d’Entity Framework, on ne peut pas créer de Complex Type dans une requête Linq To Entities.

Il nous faut donc passer via un objet anonyme pour pouvoir ensuite instancier notre complex Type.

public IQueryable<EmployeeInformation> GetEmployees()
{
var employees = from e in ObjectContext.Employees
select new { e.EmployeeID, e.FirstName, e.LastName };

return employees.ToList().ConvertAll(e => new EmployeeInformation()
{
EmployeeInformationId = e.EmployeeID,
FirstName = e.FirstName,
LastName = e.LastName
}).AsQueryable();

}

On obtient donc par la suite nos différentes données :

image

Et voilà en espérant que cette technique vous sera utile dans vos futurs développements avec RIA Services ! En plus je vous fournis tout le code source !

image

Remonter

Partager une propriété “partielle” via WCF RIA Services

AVRI2

 

J’ai présenté dans un précédent article la méthode pour ajouter une propriété à une entité issue d’un modèle Entity Framework (ou Linq To Sql) –> http://wilfriedwoivre.wordpress.com/2009/03/21/entity-framework-trucs-et-astuces/

Pour le résumé, on ajoute une propriété Total via une classe partielle sur la classe Order.

public partial class Order
{
    public decimal Total
    {
      get { return Order_Details.Sum(n => n.Quantity * n.UnitPrice); }
    }
}

Maintenant si on essaye de faire la même chose, afin de récupérer notre Total via RIA Services on s’aperçoit qu’on a un léger problème lorsqu’on regarde les différentes sources de données disponibles dans Silverlight via RIA Services.

image

Afin de rajouter notre propriété personnalisée dans notre composant Silverlight, il suffit simplement de rajouter un attribut DataMemberAttribute sur Total.

public partial class Order
{
    [DataMemberAttribute]
    public decimal Total
    {
      get { return Order_Details.Sum(n => n.Quantity * n.UnitPrice); }
    }
}

 

En fait, il suffit simplement d’ajouter cet attribut, puis que WCF RIA Services est comme son nom l’indique basé sur un service WCF.

Remonter

Entity Framework : Génération du modèle avec EF 4

JANV9

 

Pendant que j’étais en train de préparer une future présentation pour Expertime, je me suis aperçu que lors de la création du modèle Entity Framework il me proposait une option à laquelle je n’avais pas fait attention auparavant.

image

J’ai donc crée deux modèles à partir de la base NorthWind, l’un avec l’option activée, et l’autre sans, afin de pouvoir comparer.

Je me suis donc aperçu, que comme son nom l’indique cette option nomme automatiquement les objets de la base en fonction de leurs pluralités. En effet, la table “Employees” sera représenter par un objet “Employee”, et la liste des “Orders” sera représentée par la propriété de navigation “Orders”.

Cette option est je pense bien pratique, vu le nombre de fois ou je renomme tout dans mon modèle juste pour enlever des ‘s’. Par contre, je n’ai pas testé sur Visual Studio 2010 FR + SQL Server 2008 FR, mais j’espère que pour ceux qui préfèrent cette configuration que cela marche aussi.

Remonter

Entity Framework 4 : Générer des scripts Sql

SEPT16

/* Ce post a été écrit avec la version Visual Studio 2010 Beta et la CTP1 d’Entity Framework, il se peut donc qu’il ne soit plus valable lorsque vous le lirez */

Dans la version actuelle du Framework, soit la 3.5 SP1, Microsoft nous a offert Entity Framework qui est certes très puissants, mais tout de même incomplet au niveau de certaines fonctionnalités. Bien entendu, je pense à la création du script Sql ou de la base de données associée au schéma que nous avons créé. Heureusement la version 4 approchant à grand pas, avec son lot de fonctionnalité pour nous faciliter la vie, surtout sur ce point de vue.

 

Avant tout vous pouvez télécharger la version de EF4 CTP1 à cette adresse : http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=7fd7164e-9e73-43f7-90ab-5b2bf2577ac9

Et il vous faudra bien entendu Visual Studio 2010 Beta et un Sql Serveur 2008 pour que cette fonctionnalité puisse fonctionner correctement. N’oublions pas que c’est une CTP, nous n’avons qu’à espérer qu’il supporte aussi les anciennes versions de Sql (2000 & 2005)

Alors commençons par créer une application console afin d’effectuer cette démonstration, puis rajoutons notre fichier edmx en utilisant un modèle vide. Nous avons donc le designer de notre fichier vierge, ou nous pouvons ajouter les éléments que l’on souhaite. On va donc créer ici nos différents objets que l’on se servira dans notre application.

Alors prenons un modèle assez simple tel que celui ci :

image

On peut donc voir une relation n-aire entre des employés et leur entreprise, de plus on voit ici l’apparition du champ Adresse qui est un type complexe que j’ai crée comme on peut le voir dans ces propriétés :

image

Ce champ complexe contient divers autres champs. Cette possibilité aussi arrivé avec EF4 vous permettra d’extraire différents champs communs à vos tables afin de créer un objet associés à ceux ci sans pour autant à avoir à créer une table pour ceux ci. Comme typiquement ce champ adresse qui peut se retrouver aussi bien chez un contact, un employé, une entreprise, un fournisseur et qui pourtant n’a aucun lieu dans le modèle à être séparé de ces tables. image

Maintenant que nous nous sommes crée notre schéma qui va bien, que nous avons modifié certaines propriétés de notre modèle, tel que par exemple notre Entity Set Name, nous pouvons passer à la génération du script. Donc comme je l’aime bien dans Visual Studio, cette opération se trouve fortement complexe, et n’est pas disponible à ceux qui ne fouillent pas dans l’application. Mais sinon faites un clic droit et “Generate Database Script from Model …”

 

image

Donc après vous avoir choisi votre base de données, il vous génère votre fichier sql , il ne vous reste plus qu’à l’exécuter et vérifier le résultat :

image

On voit donc bien nos deux tables avec notre type complexe inclus à l’intérieur de chacune d’elle.

 

Alors pour conclure, on peut dire que cette possibilité de génération était une chose tant attendu à Entity Framework, puisque effectivement ça manquait encore à sa panoplie de compétence. Mais ceci est réglé à présent ! De plus, cela peut permettre de construire des bases de données avec une notion beaucoup plus objets grâce aux types complexes ! Cette nouvelle mouture d’Entity Framework correspond bien à l’ancienne, innovante, pratique, et bientôt indispensable pour toutes les applications.

Remonter