Partager via


Code de l'application HR Skills (Exemple d'application EDM)

Le code utilisé par l'application HRSkills illustre plusieurs fonctionnalités du modèle EDM (Modèle de données d'entité). Les schémas décrits dans les rubriques précédentes relatives à l'application HRSkills constituent la base des entités et des associations utilisées par le code de cette section. Pour plus d'informations sur les entités et les associations de cet exemple, voir Human Resources Skills WinApp (Exemple d'application EDM). Pour plus d'informations sur les métadonnées de stockage, voir Métadonnées de stockage de HR Skills (Exemple d'application EDM). Pour plus d'informations sur la spécification de mappage, voir Spécification de mappage de HR Skills (Exemple d'application EDM).

Les types conçus dans les schémas et mappés au stockage sont générés en tant que modèle objet programmable. Les données de ce modèle peuvent être programmées à l'aide de la syntaxe CLR (Common Language Runtime) sans incorporer de requêtes SQL dans le code sous forme de chaînes.

L'application montre la liaison de données aux entités, les requêtes paramétrables, ainsi que l'utilisation de propriétés de navigation sur des associations. Les associations connectent Employees à References, Employees à Skills et Skills aux entités SkillInfo qui contiennent des informations sur les compétences.

Fichier de configuration et chaîne de connexion

L'utilisation du modèle objet requiert une connexion à la base de données dans laquelle les données de l'application sont stockées. Une connexion d'entité aux objets d'exécution fournis par la DLL générée à partir des schémas est également nécessaire. Pour plus d'informations sur la construction du modèle objet à partir des schémas, voir Procédure : Procédure : utiliser EdmGen.exe pour générer un modèle EDM (Entity Framework).

Le fichier exe.config contient une chaîne de connexion utilisée pour la connexion à une base de données SQL Server et l'établissement d'une connexion d'entité. Lorsque la connexion d'entité est établie, les entités et associations du modèle objet sont accessibles à partir du code.

Le texte de la chaîne de connexion doit être ajouté au fichier exe.config par le développeur. Cette application spécifie la classe HRSkills. L'assignation providerName="System.Data.EntityClient" spécifie une connexion d'entité qui utilise le schéma de mappage défini dans le Spécification de mappage de HR Skills (Exemple d'application EDM).

La chaîne de connexion identifie également le serveur qui est utilisé par la connexion SQL : provider connection string="server=servername;.

L'exemple suivant illustre le contenu du fichier exe.config.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    
  <connectionStrings>
    <add name="HRSkills" 
         connectionString='metadata=.;
         provider=System.Data.SqlClient;
         provider connection string="server=serverName;
         database=HRSkills;
         integrated security=true;
         multipleactiveresultsets=true"'
         providerName="System.Data.EntityClient"/>
  </connectionStrings>
</configuration>

Code de l'application

Le code suivant contient les gestionnaires d'événements classiques qui s'initialisent et s'exécutent depuis un Windows Form qui sert d'interface utilisateur dans cet exemple d'application. Les directives using du préprocesseur incluent les espaces de noms nécessaires pour exécuter les requêtes de recherche d'employés, de références, de compétences et d'informations sur les compétences. La directive using finale inclut l'espace de noms HRSkillsModel qui contient les classes de runtime pour les entités et les relations du modèle objet défini et généré pour cette application, comme décrit dans les rubriques précédentes de cette section.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.Common;
using System.Data.Mapping;
using System.Data.Objects;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Data.Metadata;
using System.Linq;
using HRSkillsModel;

namespace HR_Skills_WinApp
{
    public partial class Form1 : Form
    {
        HRSkills DB = new HRSkills();
        
        public Form1()
        {
            InitializeComponent();

Une variable pour l'ObjectContext est déclarée et initialisée. HRSkills DB = new HRSkills. La connexion est contenue par l'ObjectContext et initialisée à l'intérieur des crochets try, comme le montre le segment de code qui suit. Tout message d'erreur de connexion peut être lu lors du test de l'application.

La requête initiale utilisée pour afficher tous les Employees dans le stockage utilise l'entité Employees. La classe Employees est un ObjectQuery<T> sur l'ObjectContext qui retourne toutes les entités employé.

Un contrôle DataGridView est utilisé pour afficher les résultats de la requête Employees. Des colonnes sont ajoutées au DataGridView. Le BindingSource est initialisé sur le Query<T> des Employee et la propriété DataSource du contrôle lie les données. Le paramètre true permet de mettre à jour la base de données lorsque des modifications sont apportées dans le contrôle DataGrid.

        public Form1()
        {
            InitializeComponent();

            try
            {
                bindingSource1.DataSource = DB.Employees;
                dataGridView1.DataSource = bindingSource1;
                dataGridView1.Columns[0].Visible = false;
            }
            catch(Exception e)
            {              
                System.Windows.Forms.MessageBox.Show(e.ToString());
            }
        }

Une fois les Employees affichés dans le contrôle DataGridView, les utilisateurs de l'application peuvent cliquer sur n'importe quelle ligne pour obtenir les Skills associés à l'entité Employee affichée sur cette ligne. Une nouvelle requête recherche le EmployeeId de l'entité Employee dont les données sont affichées dans le DataGridView. Le EmployeeId est masqué dans le DataGridView, mais conservé pour référence. Il est utilisé par un ObjectQuery<T> paramétrable sur Employees. Le paramètre est créé et initialisé dans la ligne : ObjectParameter param = new ObjectParameter("p", empId). Le ObjectParameter est utilisé dans la requête : DB.Employees.Where("it.EmployeeId = @p", param).First().

Une fois la classe employé identifiée et retournée par la requête, l'association Skill_Employee est utilisée pour trouver tous les Skills associés à cet employé. Une ligne de code utilise la propriété de navigation de l'employé pour charger tous les Skills associés à l'employé à partir de la base de données : Skill_Employee.GetSkillsEntities(employee).Load(). Une boucle foreach sur la même propriété de navigation lit ensuite les Skills associés à l'employé dans un deuxième contrôle DataGridView.

        private void dataGridView1_CellClick(object sender, 
            DataGridViewCellEventArgs e)
        {
            dataGridViewSkills.Columns.Clear();

            // Get the Id of the Employee and 
            Guid empId = new Guid(dataGridView1.CurrentRow.Cells[0].Value.ToString());

            // Find the Employee.
            ObjectParameter param = new ObjectParameter("p", empId);

            try
            {
                    if (null != DB.Employees.Where(
                        "it.EmployeeId = @p", param).First())
                    {

                        Employees employee = DB.Employees.Where(
                        "it.EmployeeId = @p", param).First();
                
                        employee.Skills.Load();
                        List<Skills> skillsList = new List<Skills>();
                        foreach (Skills skill in employee.Skills)
                        {
                            skillsList.Add(skill);
                        }

                        bindingSource2.DataSource = skillsList;
                        dataGridViewSkills.DataSource = bindingSource2;

                        dataGridViewSkills.Columns[0].Visible = false;
                        dataGridViewSkills.Columns[2].Width = 300;

                
                        richTextBox1.Clear();

                        // Provide EmployeeId for new skill or 
                        // reference association.
                        textBoxSkillEmployeeId.Text = 
                            employee.EmployeeId.ToString();

                        textBoxSkillEmployeeAlias.Text = employee.Alias;

                        textBoxRefEmployeeId.Text = 
                            employee.EmployeeId.ToString();

                        textBoxRefEmployeeAlias.Text = employee.Alias;
                    }

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.InnerException.ToString());
            }

        }

La méthode suivante affiche les informations sur les Skills contenue dans les entités SkillInfo d'un contrôle RichTextBox sur l'interface utilisateur. Les entités SkillInfo associées aux entités Skills sont interrogées et affichées en utilisant le même processus que la méthode précédente. Une requête prend SkillId comme paramètre et recherche une entité Skills spécifique. La propriété de navigation de l'entité Skills est parcourue pour rechercher toutes les entités SkillInfo associées à cette compétence.

Les propriétés des entités SkillInfo contiennent des URL qui identifient l'emplacement des informations supplémentaires sur les Skills associés. Dans chaque entité SkillInfo, l'URL est affichée dans la zone de texte riche.

L'entité employé associée à l'entité Skills utilisée dans cette méthode est également accessible à partir de l'entité Skills via l'association Skill_Employee. Une référence à l'employé est chargée à partir de la base de données à l'aide d'une ligne de code unique : L'employé est assigné à une variable dans une seconde ligne : L'alias de l'employé est écrit dans l'affichage de zone de texte riche.

Les références associées à l'employé sont obtenues à partir de l'association Reference_Employee. Le nom, le poste et l'adresse de messagerie de toutes les références sont contenus dans les propriétés des entités References. Ces informations sont affichées dans le Rich Text Box pour fournir des liens vers les informations sur les compétences des employés.

        private void dataGridViewSkills_CellClick(object sender, 
            DataGridViewCellEventArgs e)
        {
            richTextBox1.Clear();
            // Write the name of the skill and brief 
            // description to richtext box.
            richTextBox1.Text = richTextBox1.Text + "Skill Name: "
                + dataGridViewSkills.CurrentRow.Cells[1].
                Value.ToString() + "\n" + 
                dataGridViewSkills.CurrentRow.Cells[2].
                Value.ToString();

            // Create ObjectParameter from the SkillId property 
            // and get the Skill.
            Guid skillId =
     new Guid(dataGridViewSkills.CurrentRow.Cells[0].Value.ToString());

            ObjectParameter param = 
                new ObjectParameter("p", skillId);

            Skills skill = DB.Skills.Where("it.SkillId = @p", 
                param).First();

            // Load the SkillInfo entities using 
            // SkillInfo_Skill association.
            skill.SkillInfo.Load();
            foreach (SkillInfo skillInfo in skill.SkillInfo)
            {
                richTextBox1.Text = richTextBox1.Text +
                    "\n\nSkill Information: " + skillInfo.URL + 
                    "\n";
            }

            dataGridView1.ClearSelection();

            // Load the Employee associated with the 
            // Skill using Skill_Employee association.
            skill.EmployeeReference.Load();
            Employees employee = skill.Employee;
            if (null == employee) return;

            // Write the alias property of the Employee to rich text 
            // box and heading for references.
            richTextBox1.Text = richTextBox1.Text + 
                "\n\nEmployee: " + employee.Alias + 
                "\n\n" + "References:";

            // Load References of Employee using 
            // Reference_Employee association.
            employee.References.Load();

            foreach (References reference in employee.References )
            {
                // Write reference LastName and Position to 
                // richtext box.
                richTextBox1.Text = richTextBox1.Text + "\n" +
                    reference.FirstName + " " + reference.LastName + 
                    "  Position: " + reference.Position + 
                    "  Email: " + reference.Email;
            }

            // Provide SkillId for new SkillInfo if needed.
            textBoxSkillInfoSkillId.Text = skill.SkillId.ToString();

            for (int i = 0; i < dataGridView1.RowCount; i++)
            {
                // Check to see if this is the employee associated
                // with the skill.
                if (dataGridView1.Rows[i].Cells[0].Value.ToString()
                    == employee.EmployeeId.ToString())
                {
                    dataGridView1.Rows[i].Selected = true;
                    dataGridView1.CurrentCell = dataGridView1[1, i];

                    // Break out when the row is found.
                    break;
                }

            }            
        }

Cette application vous permet d'interroger Employees pour déterminer les compétences des employés ou d'interroger Skills pour déterminer quels employés ont les compétences référencées dans le système. La méthode qui suit utilise l'entrée utilisateur dans un contrôle TextBox pour rechercher les employés présentant les compétences décrites par l'entrée utilisateur.

Cette requête sur Skills est initialisée lorsque l'utilisateur tape des mots clés, séparés par un espace, dans le contrôle TextBox. Lorsque le bouton SkillSearch est actionné, la liste des mots clés est créée à partir de l'entrée de texte du contrôle TextBox de recherche.

Chaque mot clé de la liste est obtenu en utilisant une boucle foreach. Un ObjectParameter est créé à partir de chaque mot clé : ObjectParameter param = new ObjectParameter("p", "%" + keyword + "%"). Chaque nouvelle valeur de mot clé pour le paramètre est utilisée dans une nouvelle requête qui recherche les propriétés SkillName et BriefDescription de toutes les entités Skills du système : skillsQuery = DB.Skills.Where("it.BriefDescription Like @p OR it.SkillName Like @p", param).

Les résultats de la requête sont des entités Skills dont le nom ou la description des compétences contient un ou plusieurs des mots clés. Ces résultats sont lus dans le DataGridViewSkills. Il est ensuite possible de cliquer sur les lignes du contrôle DataGridView pour obtenir des informations sur les compétences et les références des employés. Le fait de cliquer sur une ligne dans le DataGridViewSkills déclenche le gestionnaire comme décrit précédemment. Par ailleurs, les URL SkillInfo, les Alias des employés et les References sont affichés par le contrôle Rich Text Box dans l'interface utilisateur.

        private void buttonSkillSearch_Click(object sender, EventArgs e)
        {
            dataGridViewSkills.DataSource = null;
            dataGridViewSkills.Columns.Clear();
            
            try
            {
                dataGridViewSkills.Columns.Add("idSkill", 
                    "Skill Id");
                dataGridViewSkills.Columns.Add("nameSkill", 
                    "Skill");
                dataGridViewSkills.Columns.Add("descSkill", 
                    "Description");
                dataGridViewSkills.Columns[2].Width = 300;

                // Make a list of keywords to search for in 
                // Skill entity name and description.
                List<string> keywords = new List<string>();
                int i = 0;
                int j = 0;

                while (i < textBoxKeywords.Text.Length)
                {
                    j = textBoxKeywords.Text.IndexOf(" ", i);
                    if (-1 == j) j = textBoxKeywords.Text.Length;
                    keywords.Add(
                        textBoxKeywords.Text.Substring(i, j - i));

                    i = ++j;
                }

                foreach (string keyword in keywords)
                {
                    // Create ObjectParameter from each keyword 
                    // and search properties of Skills.
                    ObjectParameter param = new ObjectParameter(
                        "p", "%" + keyword + "%");

                    ObjectQuery<Skills> skillsQuery = 
                        DB.Skills.Where(
                        "it.BriefDescription Like @p " +
                        "OR it.SkillName Like @p", param);

                    foreach (Skills skill in skillsQuery)
                    {
                        // Create an array of Skill property 
                        // strings for display.
                        string[] columnValues = 
                            new string[3] {skill.SkillId.ToString(),
                                skill.SkillName, 
                                skill.BriefDescription};

                        foreach (DataGridViewRow row in 
                            dataGridViewSkills.Rows)
                        {
                            // break if duplicate of 
                            // Skill already found.
                            if (row.Cells[0].Value != null)
                            {
                                if (row.Cells[0].Value.ToString()
                                    == columnValues[0])
                                {
                                    break;
                                }
                            }
                        }
                        dataGridViewSkills.Rows.Add(columnValues);
                    }
                }

                // Hide EmployeeId in datagrid, 
                // but keep for reference.
                dataGridViewSkills.Columns[0].Visible = false;

                richTextBox1.Clear();
            
            }

            catch(Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.ToString(),
                    "Error Message");
            }

        }

Le gestionnaire suivant permet aux utilisateurs d'appuyer sur <ENTRÉE> dans le TextBox utilisé pour commencer la recherche par mots clés au lieu de cliquer sur le bouton Search.

        private void textBoxKeywords_PreviewKeyDown(object sender, 
            PreviewKeyDownEventArgs e)
        {
            // Provide Enter activation in Search text box.
            if(e.KeyCode.Equals(Keys.Return))
                buttonSkillSearch_Click(this, System.EventArgs.Empty );
        }

Le gestionnaire suivant est appelé lorsque l'utilisateur soumet des informations qui seront utilisées pour créer une entité Employees. La méthode commence par valider les informations d'entrée, dans le cas présent, en vérifiant uniquement que textBoxLastName et textBoxAlias contiennent tous deux du texte. Une fois la nouvelle entité Employees créée, la méthode vérifie qu'il ne s'agit pas d'un doublon d'une entité Employee déjà dans le stockage avant de l'ajouter au système.

La création d'une entité Employees requiert un nouveau Guid pour la propriété EmployeeId. Les propriétés LastName, FirstName, Aliaset Email de la nouvelle entité sont assignés à partir du contenu de zones de texte renseignées par l'utilisateur.

Deux appels de méthode sont requis pour ajouter une entité au système. Le premier ajoute le nouvel objet au contexte de l'objet : DB.AddToEmployees(newEmployee). La nouvelle entité n'est pas enregistrée dans la base de données jusqu'au second appel de méthode : DB.SaveChanges().

        private void buttonSubmitEmployee_Click(object sender, 
            EventArgs e)
        {
            try
            {
                if ("".Equals(textBoxLastName.Text) || 
                    "".Equals(textBoxEmployeeAlias.Text))
                {
                    MessageBox.Show("Incomplete Information");
                    return;
                }

                // Create new Employee and add to storage.
                Employees newEmployee = new Employees();
                newEmployee.EmployeeId = Guid.NewGuid();
                newEmployee.LastName = textBoxLastName.Text;
                newEmployee.Alias = textBoxEmployeeAlias.Text;
                newEmployee.FirstName = textBoxFirstName.Text;
                newEmployee.Email = textBoxEmployeeEmail.Text;
                DB.AddToEmployees(newEmployee);

                // Check for duplicate.
                ObjectQuery<Employees> dbEmplQuery = 
                    DB.Employees.Where("it.Alias = @p", 
                    new ObjectParameter("p", newEmployee.Alias));

                if (!dbEmplQuery.Any())
                    DB.SaveChanges();

                //Refresh the Employees datagrid.
                EmployeesLabel_DoubleClick(this, null);

                textBoxFirstName.Clear();
                textBoxLastName.Clear();
                textBoxEmployeeAlias.Clear();
                textBoxEmployeeEmail.Clear();

            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.ToString(), 
                    "Error Message");
            }
        }

Le gestionnaire suivant est appelé lorsque l'utilisateur soumet des informations qui seront utilisées pour créer une entité Skills.

        private void buttonSubmitSkill_Click(object sender, EventArgs e)
        {
            try
            {
                if ("".Equals(textBoxSkillShortName.Text) || 
                    "".Equals(textBoxSkillBriefDescription.Text) || 
                    "".Equals(textBoxSkillEmployeeId.Text))
                {
                    MessageBox.Show("Incomplete Information");
                    return;
                }

                // Create new Skills entity.
                Skills newSkills = new Skills();
                newSkills.SkillId = Guid.NewGuid();
                newSkills.SkillName = textBoxSkillShortName.Text; 
                newSkills.BriefDescription = 
                    textBoxSkillBriefDescription.Text;

                DB.AddToSkills(newSkills);

                // Make a Guid of EmployeeId of Employee who 
                // has this Skill and use it in query.
                Guid empId = 
                    new Guid(textBoxSkillEmployeeId.Text);
                ObjectParameter param = 
                    new ObjectParameter("p", empId);
                Employees employee = DB.Employees.Where(
                    "it.EmployeeId = @p", param).First();

                // Add the Skill to the Skill_Employee association.
                employee.Skills.Add(newSkills);

                DB.SaveChanges();
                textBoxSkillShortName.Clear();
                textBoxSkillBriefDescription.Clear();
                textBoxSkillEmployeeId.Clear();
                textBoxSkillEmployeeAlias.Clear();

            }

            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.ToString(),
                    "Error Message");
            }
        }

Le gestionnaire suivant est appelé lorsque l'utilisateur soumet des informations qui seront utilisées pour créer une entité SkillInfo.

        private void buttonSubmitSkillInfo_Click(object sender, 
            EventArgs e)
        {
            try
            {
                if ("".Equals(textBoxSkillInfoSkillId.Text) || 
                    "".Equals(textBoxUrlUncSkillInfo.Text))
                {
                    MessageBox.Show("Incomplete Information");
                    return;
                }

                // Create new SkillInfo entity.
                SkillInfo newSkillInfo = new SkillInfo();
                newSkillInfo.SkillInfoId = Guid.NewGuid();
                newSkillInfo.URL = textBoxUrlUncSkillInfo.Text;

                // Create query and find Skill to 
                // associate with SkillInfo.
                Guid empId = 
                    new Guid(textBoxSkillInfoSkillId.Text);
                ObjectParameter param = 
                    new ObjectParameter("p", empId);
                Skills skill = 
                    DB.Skills.Where("it.SkillId = @p",
                    param).First();

                // Add SkillInfo to SkillInfo_Skill association.
                skill.SkillInfo.Add(newSkillInfo);
                DB.AddToSkillInfo(newSkillInfo);
                DB.SaveChanges();

                textBoxSkillInfoSkillId.Clear();
                textBoxUrlUncSkillInfo.Clear();
            }

            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.ToString(), 
                    "Error Message");
            }

        }

Le gestionnaire suivant est appelé lorsque l'utilisateur soumet des informations qui seront utilisées pour créer une entité References.

        private void buttonSubmitReference_Click(
            object sender, EventArgs e)
        {
            try
            {
                if ("".Equals(textBoxRefEmployeeId.Text) || 
                    "".Equals(textBoxRefEmployeeAlias.Text))
                {
                    MessageBox.Show("Incomplete Information");
                    return;
                }

                // Create new Reference and add to 
                // Reference_Employee association.
                References reference = new References();
                reference.ReferenceId = Guid.NewGuid();
                reference.LastName = textBoxRefLastName.Text; 
                reference.Email = textBoxRefEmail.Text;
                reference.Alias = 
                    textBoxRefEmail.Text.Remove(
                    textBoxRefEmail.Text.IndexOf('@'));
                reference.FirstName = textBoxRefFirstName.Text;
                reference.Position = textBoxRefPosition.Text;

                Guid empId = new Guid(
                    dataGridView1.CurrentRow.Cells[0].
                    Value.ToString());
                ObjectParameter param = new ObjectParameter(
                    "p", empId);
                Employees employee = DB.Employees.Where(
                    "it.EmployeeId = @p", param).First();

                DB.AddToReferences(reference);
                employee.References.Add(reference);

                DB.SaveChanges();

                textBoxRefFirstName.Clear();
                textBoxRefLastName.Clear();
                textBoxRefEmail.Clear();
                textBoxRefPosition.Clear();

            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.ToString(), 
                    "Error Message");
            }

        }

Le gestionnaire d'événements suivant démarre le navigateur Internet pour afficher l'URL SkillInfo écrite dans le Rich Text Box par la méthode précédente.

        private void richTextBox1_LinkClicked(object sender,
                                             LinkClickedEventArgs e)
        {  
            // Display the SkillInfo URL in Web browser.
            System.Diagnostics.Process.Start(e.LinkText);
        }

Le gestionnaire suivant est appelé lorsque l'utilisateur double-clique sur l'étiquette du DataGridViewEmployees. Il est utilisé pour actualiser le DataGridViewEmployees lorsque de nouvelles entités Employees sont ajoutées au système. Il est également appelé vers la fin du gestionnaire buttonSubmitEmployee_Click.

        private void EmployeesLabel_DoubleClick(object sender, 
            EventArgs e)
        {
            try
            {
                DB.Dispose();   //Dispose to refresh the data.
                DB = new HRSkills();
                bindingSource1.DataSource = DB.Employees;
                dataGridView1.DataSource = bindingSource1;
                dataGridView1.Columns[0].Visible = false;

            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.ToString(), 
                    "Error Message");
            }
        }

Voir aussi

Concepts

Human Resources Skills WinApp (Exemple d'application EDM)
Métadonnées de stockage de HR Skills (Exemple d'application EDM)
Spécification de mappage de HR Skills (Exemple d'application EDM)