Question

J'écris une API en utilisant WebAPI 2.0 et EF6.0 en utilisant d'abord le code.C'est donc nécessairement un scénario dbcontext déconnecté.

Mon domaine est comme ci-dessous

public class Patient
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Email ( get; set; }
    public virtual Nutritionist Nutritionist { get; set; }
}

public class Nutritionist
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual List<Patient> Patients { get; set; }
}

L'interface utilisateur permettra au patient de sélectionner un autre nutritionniste s'il n'est pas satisfait du nutritionniste actuel.Mon API doit donc prendre en charge cela.J'ai supposé qu'il s'agirait d'une simple mise à jour sur le patient.Mais le test unitaire suivant échoue.

    [TestMethod]
    public void Changing_Nutritionist_In_Disconnected_Context_Works()
    {
        Patient p;
        Nutritionist n;
        using (var c = new Context())
        {
            // Get a patient where I know p.Nutritionist.Id == 1 in database.
            p = c.Patients.Find(1);

            // Get some other nutritionist
            n = c.Nutritionists.Find(3);
        }
        using (var c = new Context())
        {
            //change patient's email and nutritionist 
            p.Email = "patient@domain.com";
            p.Nutritionist = n;

            c.Patients.Attach(p);
            c.Entry(p).State = EntityState.Modified;
            c.SaveChanges();
        }
        using (var c = new Context())
        {
            Assert.AreEqual(3,c.Patients.Find(1).Nutritionist.Id);
        }
    }

Je m'attendais à ça SaveChanges() enregistrerait les modifications apportées aux deux propriétés du patient p.Email et p.Nutritionist.Mais dans la base de données, seul l'email est modifié et Nutritionist_Id le champ continue d’afficher l’ancienne valeur.Donc, pour une raison quelconque, dbContext ignore les modifications apportées à la propriété de navigation p.Nutritionist

Le profileur SQL affiche la requête UPDATE suivante lancée par EF

exec sp_executesql N'UPDATE [dbo].[Patients]
SET [Name] = @0, [Email] = @1
WHERE ([Id] = @2)
',N'@0 nvarchar(max) ,@1 nvarchar(max) ,@2 int',@0=N'some name',@1=N'patient@domain.com',@2=1
go

Je me demande ce que je pourrais rater.

Était-ce utile?

La solution

Oui, je pourrais utiliser une propriété explicite p.NutritionistId mais j'essayais juste d'être un puriste :)

J'ai découvert que le code suivant fonctionne...

cn.Patients.Attach(p);
cn.Nutritionists.Attach(n);
cn.Entry(p).Reference(x => x.Nutritionist).Load();
p.Nutritionist = n;
cn.Entry(p).State = EntityState.Modified;
cn.SaveChanges();

Il semble que EF ne fonctionne pas automatiquement attacher les entrées associées... p.Nutritionist dans ce cas.

Aussi comme Gert Arnold mentionné dans le commentaire ci-dessus, et il ne le charge pas non plus.

Donc charger explicitement le p.Nutritionist puis changer sa valeur avec l'entité attachée rend EF heureux.

Je me demande toujours pourquoi EF ne ferait pas tout cela tout seul, car il semble logique que lorsque j'attache une nouvelle entité et la marque comme EntityState.Modified, je veux sauvegarder l'intégralité plutôt que seulement les propriétés scalaires.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top