web-dev-qa-db-fra.com

Liaison d'objets Entity Framework à un Datagridview C #

J'ai essayé de lier un objet Entity Framework à un DataGridView mais je continue de frapper des impasses et je n'arrive pas à trouver ma réponse n'importe où.

Je peux lier l'ensemble d'une table (entité) à une vue de grille et cela me permettra d'apporter des modifications et de sauvegarder ces modifications dans la base de données comme ceci:

    WS_Model.WS_Entities context;

    private void simpleButton1_Click(object sender, EventArgs e)
    {
        context = new WS_Entities();

        var query = from c in context.Users select c;

        var users = query.ToList();

        gridControl1.DataSource = users;
    }

    private void simpleButton2_Click(object sender, EventArgs e)
    {
        context.SaveChanges();
    }

mais je ne veux pas voir toutes les colonnes de la table dans ma base de données dans mon datagridview alors j'ai essayé de le faire de cette façon ...

WS_Entities context = new WS_Entities();

    private void simpleButton1_Click(object sender, EventArgs e)
    {
        var query = from c in context.Users
                    where c.UserName == "James"
                    select new { c.UserName, c.Password, c.Description };

        var results = query.ToList();

        gridControl1.DataSource = results;
    }

    private void simpleButton2_Click(object sender, EventArgs e)
    {
        context.SaveChanges();
    }

mais maintenant je ne peux pas éditer de données dans mon DataGridView.

Je ne peux pas voir le bois pour les arbres ici - s'il vous plaît, quelqu'un voudrait-il signaler notre erreur de mes manières ou me dire quelles sont les meilleures pratiques pour lier EF à Winforms alors que la fuite des cerveaux commence.

Je peux voir que cela a à voir avec la section:

select new { c.UserName, c.Password, c.Description }

Mais je ne sais pas pourquoi.

32
Jimbo James

Le problème avec la ligne:

select new { c.UserName, c.Password, c.Description }

Est-ce qu'il crée un type anonyme , et les types anonymes sont immuables - c'est-à-dire en lecture seule. C'est pourquoi vos modifications ne sont reflétées ni dans le nouveau type ni dans l'objet EF d'origine.

Maintenant, en ce qui concerne les moyens de ne pas afficher toutes les colonnes de l'objet auquel vous vous liez, j'ai donné trois options ci-dessous.

Masquer les colonnes indésirables

L'approche la plus simple consiste à définir la propriété visible sur false pour les colonnes que vous ne souhaitez pas afficher.

dataGridView1.Columns[0].Visible = false;

Où la valeur dans l'indexeur de la collection Columns peut être soit un entier spécifiant l'emplacement de la colonne, soit une chaîne pour le nom de la colonne.

Objet personnalisé dans EF pour cette liaison de données

Vous pouvez également gérer cela au niveau de la couche EF - en créant un objet personnalisé pour votre liaison qu'EF mappe à partir de la base de données sans les colonnes que vous ne voulez pas. Je n'ai pas vraiment utilisé EF 4.0, mais je comprends qu'il a maintenant cette capacité.

DTO personnalisé projeté à partir d'un objet EF puis mappé en arrière

La troisième option (et ceux-ci vont de bon à mauvais à mon avis, mais je pensais que je vous dirais quelques approches!) Consiste à interroger un type concret, puis à le mapper à l'objet EF. Quelque chose comme:

private class DataBindingProjection
{
    public string UserName { get; set; };
    public string Password { get; set; };
    public string Description { get; set; };
}

private void simpleButton1_Click(object sender, EventArgs e)
{
    context = new WS_Entities();
    var query = from c in context.Users
                where c.UserName == "James"
                select new DataBindingProjection { UserName = c.UserName, Password = c.Password, Description = c.Description };
    var users = query.ToList();
    gridControl1.DataSource = users;
}

private void simpleButton2_Click(object sender, EventArgs e) 
{
    // and here you have some code to map the properties back from the 
    // projection objects to your datacontext

    context.SaveChanges();
}

Dans certaines situations, cela pourrait aussi être une solution viable ...

38
David Hall