实体框架未在更新时保存所有属性

时间:2016-07-01 09:54:04

标签: c# entity-framework getter-setter

我正在尝试使用自定义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都有正确的数据。 <{1}}和Name会更新。

但是,如果删除EnabledName的分配,Enabled会更新。

它确实可以在实体创建时使用,而不是在更新时。我还想指出我无法访问SettingsJson

1 个答案:

答案 0 :(得分:3)

  1. 我猜测实体框架并不知道它应该更新数据库中的SettingsJson,因为您从不直接在代码中修改它。是的,您修改Settings的getter中使用的SettingsJson对象,但Entity Framework不会以这种方式跟踪对象。

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

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

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

  2. 编辑:

    1. 如果您无法访问DbContext ,则必须直接设置SettingsJson属性,以便让Entity Framework更新它数据库。我知道在您当前的实现中,您永远不必担心更新实际字典和字典的JSON表示,但这对于Entity Framework来说是不可能的。你必须尝试这样的事情:

      public virtual string SettingsJson { get; set; } // just an auto-implemented property
      
      ...
      
      existingEntity.Settings = dto.Settings;
      existingEntity.SettingsJson = JsonConvert.SerializeObject(dto.Settings);
      // save changes
      
    2. 另一个解决方案可能是在SettingsJson的设置器中直接设置Settings,如下所示:

      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表添加到数据库模型中?