【问题标题】:EF 4.1 Issue retrieving original and current valuesEF 4.1 检索原始值和当前值的问题
【发布时间】:2013-06-22 19:12:49
【问题描述】:

我正在使用 EF 4.1 和延迟加载。我有以下实体:

public abstract class PersonBase
{
   [Key(), Required]
   [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
   public int Id { get; set; }

   ....
   [ForeignKey("Quantity")]
   public virtual int? QuantityId { get; set; }
   public virtual Quantity Quantity { get; set; }
   ....
}

public class ConcretePerson : PersonBase
{
  ....
}

public class Quantity
{
    [Key(), Required]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    [Required]
    public virtual float QuantityA { get; set; }

    [Required]
    public virtual float QuantityB { get; set; }

    [Required]
    public virtual float QuantityC { get; set; }
}

IDbSet<Quantity> Quantities;
IDbSet<ConcretePerson> ConcretePersons;
IDbSet<PersonBase> Persons;

所以在我的代码中我执行如下:

using (DataBaseContext context = new DataBaseContext())
{
    IQueryable<ConcretePerson> concretePersonCollection = context.ConcretePersons.Where(<condition>);
    foreach (ConcretePerson concretePerson in concretePersonCollection)
    {
        ...
        concretePerson.Quantity.QuantityA = new_quantity_A;
        concretePerson.Quantity.QuantityB = new_quantity_B;
        concretePerson.Quantity.QuantityC = new_quantity_C;
        ...
    }

    ...

    DbEntityEntry<ConcretePerson> entityEntry;
    Quantity quantity;
    foreach (ConcretePerson concretePerson in concretePersonCollection)
    {
       entityEntry = context.Entry<ConcretePerson>(concretePerson);
       if (entityEntry.State == System.Data.EntityState.Modified)
       {
           quantity = ((ConcretePerson)entityEntry.CurrentValues.ToObject()).Quantity;
       }
       else
       {
           quantity = concretePerson.Quantity;
       }

       ...
    }   

    ...

    context.SaveChanges();
}


请注意,我只在最后执行 SaveChanges,因此在达到这一点之前不会更新数据库。

我在第二个 foreach 中遇到问题:
1.- 当 entityEntry.State 被修改时, ((ConcretePerson)entityEntry.CurrentValues.ToObject()).Quantity 为 null 但 ((ConcretePerson)entityEntry.CurrentValues.ToObject()).QuantityId 是正确的(包含正确的值) 为什么?如何使用当前值(既不是原始值也不是数据库值)仅使用当前值来获得与 null 不同的值?

2.- 如果我通过执行concretePerson.Quantity 直接检查数量,它不是空的,而是 具体Person.Quantity 包含当前值(在第一次 foreach 中更新的值), 不是原始的(在第一个 foreach 中更新之前的值)。不应该是具体的Person.Quantity 包含原始值(在第一个 foreach 中更新之前)?因为我没有 在两个 foreach 循环之间执行任何 context.savechanges。
3.-Context.SaveChanges 没有保存对数据库所做的更改,也没有引发任何错误。

【问题讨论】:

    标签: entity-framework


    【解决方案1】:
    1. 这是一种尝试获取值的奇怪方式...试试this

    2. concretePerson.Quantity 将是实体的 local 副本,因此它具有您分配给它的任何值。

    在第一个 foreach 中,您实际上是在修改集合中的每个项目(即使它没有保存到数据库但它仍在内存中,否则 EF 怎么知道要保存到数据库中的内容?)。

    在第二个中,您实际上是在检查同一个集合以查看实体是否已被修改(它们已被修改),然后获取当前值。但是,数量的当前值将与 .quantity 相同,因为您已修改实体。如果您检查修改条目的 original 值,您会发现它有所不同。

    基本上 CurrentValue 是内存中实体的值(如果您更改 CurrentValue 属性更改)。原始值为"usually the entity's property values as they were when last queried from the database"

    1. 没关系;p

    【讨论】:

    • 对于第 2 点:当您说它将是本地副本时,我认为您指的是当前值,对吗?但为什么是当前值?它不应该是原始价值吗?我不明白。你能给我解释一下吗?在到达 foreach 之前不会执行查询。所以第一个 foreach 是从数据库中检索当前数据,但是第二个 foreach,当再次执行查询时,数据来自哪里?你说的是当前值,但为什么呢?数据库值不能是因为没有提交保存更改,但为什么它们不是第二个 foreach 中的原始值?
    • 好的,谢谢,我现在明白了,但有一个小问题:正如您所说,OriginalValue 是“通常是实体的属性值,就像上次从数据库中查询时一样”,所以在我的第二个 foreach 中,查询在“foreach(ConcretePersonconcretePerson inconcretePersonCollection)”中再次执行,那么当 foreach 被击中时读取的值在哪里?数据库?还是在记忆中?
    • 据我所知,第一个查询将从数据库中获取数据并将其存储在内存中。第二次查询时,它将查询内存中的集合。从数据库中获取新/更新数据的唯一方法是销毁上下文并创建一个新的或使用 EntityEntry.Reload() 方法从数据库中刷新该实体。
    • 为什么 EF 在第二次 foreach 中决定从内存集合中而不是从数据库中获取数据? EF 如何知道它必须在第二个 foreach 中从内存集合中获取数据?提供了很好的信息!很好的评论和很好的解释。非常感谢您的 cmets 并帮助我更多地了解 EF 行为。
    猜你喜欢
    • 2021-01-03
    • 2020-09-21
    • 1970-01-01
    • 1970-01-01
    • 2011-07-24
    • 2014-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多