【问题标题】:Entity Framework not saving all properties on update实体框架未在更新时保存所有属性
【发布时间】:2016-07-03 06:17:40
【问题描述】:

我正在尝试使用自定义 getter 和 setter 更新实体,但如果我编辑实体上的任何其他属性,它们不会被保存。我有一个 DTO,它映射到检索到的实体。

DTO:

public class MyEntityDto
{
    public string Id { get; set; }

    public string Name { get; set; }

    public bool Enabled { get; set; }

    public Dictionary<string, string> Settings { get; set; }
}

实体:

public class MyEntity
{
    public virtual Guid Id { get; set; }

    public virtual string Name { get; set; }

    public virtual bool Enabled { get; set; }

    public Dictionary<string, string> Settings { get; set; }

    public virtual string SettingsJson
    {
        get { return JsonConvert.SerializeObject(Settings); }
        set
        {
            Settings = JsonConvert.DeserializeObject<Dictionary<string, string>>(value);
        }
    }
}

更新功能:

public async Task UpdateAsync(dto MyEntityDto)
{
    var existingEntity = await _myRepository.GetByIdAsync(dto.Id);

    existingEntity.Name = dto.Name;
    existingEntity.Enabled = dto.Enabled;
    existingEntity.Settings = dto.Settings;

    await _myRepository.Update(existingEntity);

    // save changes happens at end of request
}

我的SettingsJson 没有更新。我已经完成了它,existingEntity.SettingsJsonexistingEntity.Settings 都有正确的数据。 NameEnabled 会更新。

但是,如果我删除 NameEnabled 的分配,SettingsJson 确实会更新。

它确实适用于实体创建,但不适用于更新。我还想指出我无权访问DbContext

【问题讨论】:

  • 我注意到在你的实体类中,除了字典对象之外,所有的实体类都被声明为虚拟的。
  • @bilpor EF 无论如何都不支持字典,因此它不会存储在数据库中。
  • QueueSettings 是什么?
  • @RuudLenders 抱歉只是想说Settings

标签: c# entity-framework getter-setter


【解决方案1】:
  1. 我猜 Entity Framework 不知道它应该更新数据库中的SettingsJson,因为您从不直接在代码中修改它。是的,您修改了SettingsJson 的getter 中使用的Settings 对象,但Entity Framework 不会以这种方式跟踪对象。

    在修改 Settings 对象后尝试此操作,但在进行实际更新之前:

    _myDbContext.Entry(existingEntity).Property(e => e.SettingsJson).IsModified = true;
    

    但是,此代码假定您的 DbContext 已公开,但情况可能并非如此。

编辑:

  1. 如果您无权访问DbContext,则必须直接设置SettingsJson 属性才能让实体框架在数据库中更新它。我知道,在您当前的实现中,您永远不需要担心更新实际字典和字典的 JSON 表示,但实体框架无法做到这一点。你必须尝试这样的事情:

    public virtual string SettingsJson { get; set; } // just an auto-implemented property
    
    ...
    
    existingEntity.Settings = dto.Settings;
    existingEntity.SettingsJson = JsonConvert.SerializeObject(dto.Settings);
    // save changes
    
  2. 另一种解决方案可以直接在Settings的setter中设置SettingsJson,像这样:

    private Dictionary<string, string> settings // private backing field
    public Dictionary<string, string> Settings
    {
        get { return settings; }
        set
        {
            settings = value;
            SettingsJson = JsonConvert.SerializeObject(dto.Settings); // EF tracks this
        }
    }
    

    然而,如果在设置字典后添加元素,则需要再次重新序列化字典,以更新 JSON 字符串。您可以通过使用某种可观察字典来动态解决此问题,但请确保它只在需要时(在调用更新数据库之前)序列化字典一次。

  3. 这并不是真正的解决方案,但值得深思。数据库不理解字典。您知道,这就是您使用 JSON 来帮助您的原因。但是,为什么不简单地将Setting 表添加到您的数据库模型中呢?

【讨论】:

  • 是的,很遗憾我无法访问上下文。因此,如果我从不直接修改代码中的属性,它如何在创建时成功保存它?有什么不同吗?
  • @KevinLee 是的,创建是不同的。插入新记录时,实体框架会收到一个未被上下文跟踪的对象。它不知道哪些属性已设置,哪些未设置,因此在插入时会全部使用它们。更新 EF 时依赖于跟踪,这就是它不理解 SettingsJson 的原因。如果您无权访问上下文,请参阅我更新的解决方法。
  • 非常感谢您的回答。我明白现在发生了什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多