Disons que j'interroge la base de données et charge une liste d'éléments. J'ouvre ensuite l'un des éléments dans un formulaire de vue détaillée et, au lieu de réinterroger l'élément en dehors de la base de données, je crée une instance de l'élément à partir de la source de données dans la liste.
Est-il possible de mettre à jour l'enregistrement de base de données sans extraire l'enregistrement de l'élément en question?
Voici un exemple de la façon dont je le fais maintenant:
dataItem itemToUpdate = (from t in dataEntity.items
where t.id == id
select t).FirstOrDefault();
Puis, après avoir extrait l’enregistrement, je mets à jour certaines valeurs de l’article et pousse l’enregistrement:
itemToUpdate.itemstatus = newStatus;
dataEntity.SaveChanges();
Je penserais qu'il y aurait une meilleure façon de faire ceci, des idées?
Vous devriez utiliser la méthode Attach () .
Vous pouvez également utiliser le SQL direct sur la base de données en utilisant le contexte du magasin de données. Exemple:
dataEntity.ExecuteStoreCommand
("UPDATE items SET itemstatus = 'some status' WHERE id = 123 ");
Pour des raisons de performances, vous souhaiterez peut-être transmettre des variables plutôt qu'une chaîne SQL codée en dur. Cela permettra à SQL Server de mettre en cache la requête et de le réutiliser avec des paramètres. Exemple:
dataEntity.ExecuteStoreCommand
("UPDATE items SET itemstatus = 'some status' WHERE id = {0}", new object[] { 123 });
UPDATE - pour EF 6.0
dataEntity.Database.ExecuteSqlCommand
("UPDATE items SET itemstatus = 'some status' WHERE id = {0}", new object[] { 123 });
Si la DataItem
a des champs EF sera pré-validé (comme les champs non nullables), nous devrons désactiver cette validation pour ce contexte:
DataItem itemToUpdate = new DataItem { Id = id, Itemstatus = newStatus };
dataEntity.Entry(itemToUpdate).Property(x => x.Itemstatus).IsModified = true;
dataEntity.Configuration.ValidateOnSaveEnabled = false;
dataEntity.SaveChanges();
//dataEntity.Configuration.ValidateOnSaveEnabled = true;
Sinon, nous pouvons essayer de satisfaire la pré-validation et de ne mettre à jour que la colonne unique:
DataItem itemToUpdate = new DataItem
{
Id = id,
Itemstatus = newStatus,
NonNullableColumn = "this value is disregarded - the db original will remain"
};
dataEntity.Entry(itemToUpdate).Property(x => x.Itemstatus).IsModified = true;
dataEntity.SaveChanges();
En supposant que dataEntity
est un System.Data.Entity.DbContext
Vous pouvez vérifier la requête générée en l'ajoutant à la DbContext
:
/*dataEntity.*/Database.Log = m => System.Diagnostics.Debug.Write(m);
Le code:
ExampleEntity exampleEntity = dbcontext.ExampleEntities.Attach(new ExampleEntity { Id = 1 });
exampleEntity.ExampleProperty = "abc";
dbcontext.Entry<ExampleEntity>(exampleEntity).Property(ee => ee.ExampleProperty).IsModified = true;
dbcontext.Configuration.ValidateOnSaveEnabled = false;
dbcontext.SaveChanges();
Le résultat TSQL:
exec sp_executesql N'UPDATE [dbo].[ExampleEntities]
SET [ExampleProperty ] = @0
WHERE ([Id] = @1)
',N'@0 nvarchar(32),@1 bigint',@0='abc',@1=1
Remarque:
La ligne "IsModified = true" est nécessaire car, lorsque vous créez le nouvel objet ExampleEntity (uniquement avec la propriété Id renseignée), toutes les autres propriétés ont leurs valeurs par défaut (0, null, etc.). Si vous souhaitez mettre à jour la base de données avec une "valeur par défaut", la modification ne sera pas détectée par la structure de l'entité, puis la base de données ne sera pas mise à jour.
Par exemple:
exampleEntity.ExampleProperty = null;
ne fonctionnera pas sans la ligne "IsModified = true", car la propriété ExampleProperty est déjà nulle lorsque vous avez créé l'objet ExampleEntity vide. Vous devez donc indiquer à EF que cette colonne doit être mise à jour.
Cet article faisant partie de Prise en main de Microsoft explique les états des entités et comment procéder:
Ajouter/attacher et états d'entité
Regardez la section 'Attacher une entité existante mais modifiée au contexte'
Maintenant, je pars pour lire le reste de ces tutoriels.
En règle générale, si vous avez utilisé Entity Framework pour interroger tous les éléments et que vous avez enregistré l'objet entité, vous pouvez mettre à jour les éléments individuels dans l'objet entité et appeler SaveChanges()
lorsque vous avez terminé. Par exemple:
var items = dataEntity.Include("items").items;
// For each one you want to change:
items.First(item => item.id == theIdYouWant).itemstatus = newStatus;
// After all changes:
dataEntity.SaveChanges();
La récupération de l'élément souhaité ne doit pas générer de nouvelle requête.
Cela fonctionne un peu différemment dans EF Core:
Il existe peut-être un moyen plus rapide de le faire dans EF Core, mais les éléments suivants garantissent une mise à jour sans devoir effectuer de sélection (testé avec EF Core 2 et JET sur .NET Framework 4.6.2):
Assurez-vous que votre modèle n'a pas de propriétés IsRequired
Ensuite, utilisez le modèle suivant (dans VB.NET):
Using dbContext = new MyContext()
Dim bewegung = dbContext.MyTable.Attach(New MyTable())
bewegung.Entity.myKey = someKey
bewegung.Entity.myOtherField = "1"
dbContext.Entry(bewegung.Entity).State = EntityState.Modified
dbContext.Update(bewegung.Entity)
Dim BewegungenDescription = (From tp In dbContext.Model.GetEntityTypes() Where tp.ClrType.Name = "MyTable" Select tp).First()
For Each p In (From prop In BewegungenDescription.GetProperties() Select prop)
Dim pp = dbContext.Entry(bewegung.Entity).Property(p.Name)
pp.IsModified = False
Next
dbContext.Entry(bewegung.Entity).Property(Function(row) row.myOtherField).IsModified = True
dbContext.SaveChanges()
End Using