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

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

Silverlight 3.0 et les .Net RIA Services

AOÛT12

Dans la continuité d’un de mes articles sur Silverlight et les différents moyens d’accéder aux données soit via l’utilisation du JSon, ou par des services Web (WCF …). Il en manquait inévitablement un sur les .Net RIA Services. Alors les .Net RIA Services en deux mots, qu’est-ce que c’est, c’est une nouvelle mouture d’ADO.Net pour Silverlight. En effet, lors de la conception d’application Silverlight, on avait vu que cela péchait pour récupérer les données, vu que Silverlight est une technologie cliente. Il fallait donc, comme le montre le schéma ci-dessous  pour accéder aux données contenues dans notre base depuis notre interface, passer par le code métier et ensuite, via un service arrivé à notre base de données pour effectuer la requête. C’est donc ce que l’on appelle une architecture n-tiers, facile à implémenter et facilement maintenable. image Cependant ce découpage est bien souvent pas respecté pour beaucoup de projets, il n’est donc pas rare de voir les différentes parties clientes mélangées, ainsi que le côté serveur pour des questions de rapidité de développement. On a donc généralement une architecture de ce type pour finir. image Cette facilité de développement, j’avoue peut être intéressante dans l’instant lorsque l’on n’a absolument pas l’habitude de bien séparer les diverses couches d’une application, ou que l’on ne veut pas implémenter de Design Pattern (comme le MVVM) dans son projet en plus. Néanmoins, la reprise de tel projet par la suite est d’autant plus dur … Alors maintenant, voyons comment nous structurons nos données avec .Net RIA Services image Bon maintenant que nous avons vu comment est construit une application Silverlight utilisant les .Net RIA Services, on va pouvoir en faire une. Alors pour base de données, je vais prendre celle de NorthWind non modifié, vous pouvez la trouver à ce lien si vous ne l’avez pas. Alors pour commencer nous allons créer une nouvelle application Silverlight de type Business Application. Ce type d’application est ajouté après avoir installer les .Net RIA Services. Maintenant que notre projet est créé, nous allons accéder à notre base, donc dans notre projet ASP.Net, nous allons créer cet accès avec Entity Framework,  avec lequel nous allons récupérer tous les employés de la base Northwind. Donc jusque là, rien de bien anormal par rapport à un autre projet Silverlight que vous auriez pu faire avant. Maintenant, toujours dans le projet ASP.Net, nous allons créer un nouvel item qui s’appelle “Domain Service Class”, on peut le trouver dans la partie Web, comme on peut le voir ci dessous : image Maintenant, nous avons un deuxième écran qui nous demande quels éléments seront disponibles du côté client. Pour la démonstration, nous allons donc choisir les “Employees”, et la possibilité d’éditer ceux-ci. image Cette classe nous génère donc entre autre ce code ci :
    // Implements application logic using the NorthwindEntities context.
    // TODO: Add your application logic to these methods or in additional methods.
    [EnableClientAccess()]
    public class NorthwindDomainService : 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<Employees> GetEmployees()
        {
            return this.Context.Employees;
        }

        public void InsertEmployees(Employees employees)
        {
            this.Context.AddToEmployees(employees);
        }

        public void UpdateEmployees(Employees currentEmployees)
        {
            this.Context.AttachAsModified(currentEmployees, this.ChangeSet.GetOriginal(currentEmployees));
        }

        public void DeleteEmployees(Employees employees)
        {
            if ((employees.EntityState == EntityState.Detached))
            {
                this.Context.Attach(employees);
            }
            this.Context.DeleteObject(employees);
        }
    }
}
Comme on peut le voir, cette action nous permet de générer tous ce qu’il faut pour lire et modifier des employés de la base, bien entendu rien ne vous empêche d’en rajouter, pour des questions de performances, comme par exemple, une partie qui ne retourne seulement 10 employés de la base au lieu de toute la base. L’autre partie qui est généré sont les metadatas nécessaire pour le bon fonctionnement de la communication avec les .Net RIA Services. Donc maintenant qu’on a crée notre partie accès aux données, ainsi que notre code métier, et le service pour accéder à nos données, nous n’avons plus qu’à gérer le côté client en Silverlight. Alors commençons par la partie XAML, pour notre exemple, nous allons afficher les noms et les prénoms des employés de la base de données :
                <ListBox ItemsSource="{Binding}" Margin="0,50,0,0" Height="300">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <StackPanel Orientation="Horizontal" >
                                <TextBlock Text="{Binding FirstName}"
                           Width="250" />
                                <TextBlock Text="{Binding LastName}" />
                            </StackPanel>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
Nous allons maintenant charger les données depuis la base grâce aux RIA Services :
private void Page_Loaded(object sender, RoutedEventArgs e)
{
    var context = new NorthwindDomainContext();
    DataContext = context.Employees;
    context.Load(context.GetEmployeesQuery());
}
Nous chargeons les données de façon assez simple, grâce à une requête Linq, ou à la méthode context.GetEmployeesQuery() qui renvoie ceci :
public EntityQuery<Employees> GetEmployeesQuery()
{
    return base.CreateQuery<Employees>("GetEmployees", null, false, true);
}
Soit toutes les données de la table Employees. Bien entendu, toutes ces opérations avec .Net RIA Services sont asynchrone afin que l’application reste fluide pour l’utilisateur. Alors pour conclure sur cet article, et sur cette technologie, les .Net RIA Services sont très puissant pour toutes les applications Business, néanmoins la faille que je vois par rapport à un service classique en WCF, c’est que les .Net RIA Services sont orientés uniquement pour Silverlight, alors qu’un service WCF permet de partager l’accès aux services entre divers types d’application. Voilà bien entendu je vous fournis le code source de l’application, il faudra bien entendu changer la chaine de connexion à la base de données. image Ressouces : Un très bon lien sur .Net RIA Services que je vous conseille : http://blogs.msdn.com/brada/archive/tags/RIAServices/default.aspx
Remonter