4

I have a DbContext with ProxyCreationEnabled set to true (actually it's the default value).

As far as I remember, this enables EF to load proxy entities from database, so any change we make to properties are recognized by the change tracker, and we can call SaveChanges() like this:

using (var db = new MyDbContext())
{
    var people = db.People.Where(p => p.Status = PersonStatus.New).ToList();
    foreach (var person in people)
    {
        person.Name = "Something";
    }
    db.SaveChanges();
}

The problem is: why would EF not use the proxy for a specific class, even though ProxyCreationEnabled is true? The class is not sealed, so it should be able to use proxy.

Here is my sample class:

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime RegisterDate { get; set; }
    public PersonStatus Status { get; set; }
}
7
  • It looks correct. Could it just be the p.Status =, it should be two equal signs. I would try with First() instead of tolist to test a single record. Commented Jan 4, 2018 at 13:11
  • @ThomasKoelle thanks for your help, actually that was a typo, in the actual code there are two equal signs. Either First() or ToList() return the class instead of the proxy. Commented Jan 4, 2018 at 13:19
  • "The problem is: ..." As soon as the query is not no tracking (your is not), you don't rely on lazy loading and AutoDetectChangesEnabled is true, the lack of proxy should not be a problem at all. Commented Jan 4, 2018 at 13:21
  • 1
    Correct. Because EF DbContext "tracks" the entity instances internally, including the original and current values. Commented Jan 4, 2018 at 13:33
  • 1
    @IvanStoev I didn't know that. In my case, values are not being persisted, but now that you said that, I think that's something else. I'm using AutoMapper to update the values from one list of objects (e.g PersonViewModel) to the destination existing entities. I thought it was due to proxies, since AutoMapper keeps the destination instances. I'm going to do more tests. Anyway, my question was properly answered by MegaTron, but you pointed something really interesting. Commented Jan 4, 2018 at 13:43

1 Answer 1

2

To generate proxy for property it should be virtual

public class Person
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual DateTime RegisterDate { get; set; }
    public virtual PersonStatus Status { get; set; }
}

To get change tracking proxies, the basic rule is that your class must be public, non-abstract or non-sealed. Your class must also implement public virtual getters/setters for all properties that are persisted. Finally, you must declare collection based relationship navigation properties as ICollection<T> only. They cannot be a concrete implementation or another interface that derives from ICollection<T> (a difference from the Deferred Loading proxy)

Sign up to request clarification or add additional context in comments.

1 Comment

After changing all properties to virtual, it worked. The strange thing is that if I have at least one non-virtual property, EF won't use proxy. But I have other classes with non-virtual properties, and it does use proxy. What's wrong with this specific class?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.