为什么Entity Framework没有生成代理?

4

我有一个DbContextProxyCreationEnabled设置为True(实际上这是默认值)。

据我所知,这使EF能够从数据库加载代理实体,因此我们对属性所做的任何更改都会被更改跟踪器识别,并且我们可以像这样调用SaveChanges()

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();
}

问题是:为什么即使启用了ProxyCreationEnabled,EF也不会对特定类使用代理?该类没有被密封,因此应该能够使用代理。

以下是我的示例类:
public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime RegisterDate { get; set; }
    public PersonStatus Status { get; set; }
}

看起来没问题。可能只是p.Status =应该是两个等号。我建议尝试使用First()而不是tolist来测试单个记录。 - Thomas Koelle
@ThomasKoelle 感谢您的帮助,实际上那是一个打字错误,在实际代码中有两个等号。First()ToList() 会返回类而不是代理。 - Alisson Reinaldo Silva
@IvanStoev 如果我理解正确的话,EF应该能够更新任何对实体所做的更改,即使它们不是代理? - Alisson Reinaldo Silva
1
正确。因为EF DbContext在内部“跟踪”实体实例,包括原始值和当前值。 - Ivan Stoev
1
@IvanStoev 我不知道那个。在我的情况下,值没有被持久化,但是现在你说了,我认为那是另外一件事情。我正在使用 AutoMapper 将一个对象列表(例如 PersonViewModel)的值更新到目标现有实体中。我以为这是由于代理引起的,因为 AutoMapper 保留了目标实例。我将进行更多的测试。无论如何,我的问题得到了 MegaTron 的正确回答,但你指出了一些非常有趣的东西。 - Alisson Reinaldo Silva
显示剩余2条评论
1个回答

2

要为属性生成代理,它应该是虚拟的。

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; }
}

要获取更改跟踪代理,基本规则是您的类必须是公共的、非抽象的或非密封的。您的类还必须为所有持久化属性实现公共虚拟的getter/setter。最后,您必须将基于集合的关系导航属性声明为仅限ICollection<T>。它们不能是具体实现或从ICollection<T>派生的另一个接口(这与延迟加载代理不同)。

将所有属性更改为虚拟属性后,它就可以工作了。奇怪的是,如果我至少有一个非虚拟属性,EF 就不会使用代理。但是我有其他具有非虚拟属性的类,它确实使用代理。这个特定的类有什么问题? - Alisson Reinaldo Silva

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接