2
votes

Pourquoi context.SaveChanges () met-il à jour chaque ligne de la table?

J'ai écrit du code en utilisant C # et Entity Framework 6 (EF6) avec MySql. L'EDI est l'aperçu de Visual Studio 2019.

J'ai installé ces packages:

class Car
{
    public int CarId { get; set; }
    public string Model { get; set; }
    public int Year { get; set; }
    public string Manufacturer { get; set; }
}

L'insertion et la sélection fonctionnent correctement mais la mise à jour fonctionne sans fil.

J'ai mis un nombre (quelque chose comme 2 ou 100) dans tbx_CarId et je m'attendais à ce que EF6 ne mette à jour qu'une seule ligne, mais il met à jour chaque bas de la table.

[DbConfigurationType(typeof(MySqlEFConfiguration))]
class Parking : DbContext
{
    public DbSet<Car> Cars { get; set; }

    public Parking()
      : base()
    {
        // constructor is empty
    }

    // Constructor to use on a DbConnection that is already opened
    public Parking(DbConnection existingConnection, bool contextOwnsConnection)
      : base(existingConnection, contextOwnsConnection)
    {
        // constructor is empty
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<Car>().MapToStoredProcedures();
    }
}

La méthode context.SaveChanges () renvoie toujours un nombre exact, 1, et sur la fenêtre de la console, "numOfSavedLows: 1" est affiché.

Mais chaque ligne est modifiée chaque fois que j'exécute cette méthode.

De plus, l'enregistreur d'EF6 écrit sur la console quelque chose comme ceci:

Started transaction at 2019-01-03 오후 6:47:59 +09:00
`Car_Update`
-- CarId: '2' (Type = Int32, IsNullable = false)
-- Model: 'new value of the model' (Type = String, IsNullable = false, Size = 5)
-- Year: '2013' (Type = Int32, IsNullable = false)
-- Manufacturer: 'Dodge' (Type = String, IsNullable = false, Size = 5)
-- Executing at 2019-01-03 오후 6:47:59 +09:00
-- Completed in 6 ms with result: 16

Committed transaction at 2019-01-03 오후 6:47:59 +09:00
Disposed transaction at 2019-01-03 오후 6:47:59 +09:00

Veuillez regarder la ligne - Terminé en 6 ms avec le résultat: 16 Le nombre (dans ce cas, 16) est le décompte de chaque ligne dans le tableau Car .

Pourquoi EF6 se met-il à jour à chaque bas? Comment puis-je résoudre ce problème?

Le reste des codes se trouve ici:

private void btn_update_Click(object sender, EventArgs e)
{
    using (MySqlConnection connection = new MySqlConnection(connectionString))
    {
        connection.Open();

        using (Parking context = new Parking(connection, false))
        {
            context.Database.Log = (string message) => { Console.WriteLine(message); };

            int targetId = Int32.Parse(tbx_CarId.Text);
            var blogs = from b in context.Cars
                        where b.CarId == targetId
                        select b;
            Car item = blogs.Single();
            item.Model = tbx_NewModel.Text;
            int numOfSavedLows = context.SaveChanges();
            Console.WriteLine("numOfSavedLows: " + numOfSavedLows.ToString());
        }
    }
}

et

<packages>
  <package id="EntityFramework" version="6.2.0" targetFramework="net461" />
  <package id="MySql.Data" version="6.10.8" targetFramework="net461" />
  <package id="MySql.Data.Entity" version="6.10.8" targetFramework="net461" />
</packages>

La plupart des codes proviennent d'ici: https://dev.mysql.com/doc/connectors/ fr / connector-net-entityframework60.html

mise à jour 1: Le tableau Voitures ressemble à ceci (Le schéma et la table sont générés automatiquement par EF6)

mise à jour 2: Les valeurs des lignes sont comme ceci: Avant et Après (les arguments sont 8, "nouvelle valeur")

p >


5 commentaires

Êtes-vous sûr que 16 lignes ont été mises à jour? Peut-être que la table contient un index et qu'elle a été reconstruite? Avez-vous utilisé le profileur pour voir le code SQL généré?


Cela ne peut se produire que lorsque CarId n'est pas unique et qu'il y a 16 enregistrements ayant CarId == 2 .


Avez-vous vérifié l'état des entités dans le ChangeTracker de votre DbContext? Tous doivent être égaux à EntityState.Unchanged, à l'exception de l'entité que vous avez modifiée.


Lorsque vous exécutez une trace de base de données (ou utilisez hibernatingrhinos.com/products/efprof ) pour voir le commandes exactes envoyées à la base de données, qu'est-ce qui est soumis?


Pouvez-vous aller dans la base de données et trouver la procédure Car_Update ?


3 Réponses :


0
votes

Context.Savechanges () trouve tous les changements dans tous les dbsets (entités) et les valide tous dans la base de données, c'est un tirage dans le framework Entity.


1 commentaires

Pourtant, il n'a changé qu'une seule ligne. Le ChangeTracker du DbContext doit contenir tous les éléments, mais la plupart d'entre eux doivent avoir un état égal à EntityState.Unchanged.



0
votes

Je suppose que votre entité n'a pas de colonne principale définie. De cette façon, Entity Framework ne peut pas sélectionner les données de corrélation dans la table avec votre entité et met à jour chaque ligne où «tout» (chaque entrée correspond à la définition de clé primaire) remplit la condition. Vous devez ajouter quelque chose comme

[Key, Column("Car_ID_IN_DB"), DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int CarId{ get; set;}

à votre table Cars modélisée sur votre CarId (vous n'affichez pas cette définition) p>

Cela ne fonctionne que si vous utilisez CodeFirst, si vous utilisez DbFirst, vous devez vérifier l'entité générée de Cars si elle est correctement modélisée et si vous avez modélisé une clé primaire dans votre base de données.


1 commentaires

Mais la table Cars a une clé primaire ... La colonne CarId est la clé primaire. regarde ça. i.stack.imgur.com/x1cle.png



0
votes

Comme suggéré dans EF6 GitHub officiel ,

La suppression de MapToStoredProcedure dans mon DbContext résout le problème.

Je vous dirais d'essayer de supprimer le code "MapToStoredProcedures ()" et de voir si vous obtenez un résultat différent.


0 commentaires