EF6 设置默认属性禁用更改跟踪

Posted

技术标签:

【中文标题】EF6 设置默认属性禁用更改跟踪【英文标题】:EF6 setting default property disables change tracking 【发布时间】:2021-10-15 10:40:57 【问题描述】:

在 .NET 4.7 上使用 EF6 WebApi 并在我们设置默认值时尝试保存模型更新时遇到问题。我正在使用以下模式在 EF6 中保存 JSON 属性,它适用于许多类:

public class User 

...
    public int AddressId  get; set; 
    public string AddressName  get; set; 
    // New fields for mapping 1-N Address
    [NotMapped]
    public List<Address> Addresses
    
        get  return JsonConvert.DeserializeObject<List<Address>>(AddressesJson ?? string.Empty); 
        set  AddressesJson = JsonConvert.SerializeObject(value); 
    
    [MaxLength(5000), JsonIgnore]
    public string AddressesJson  get; set; 
...


public class Address

    public string Id  get; set; 
    public string Name  get; set; 

当我们尝试设置默认值时会出现问题。如果Addresses == null,我们希望迁移用户对象上的现有地址。所以我们尝试了以下方法:

public class User 

...
    [NotMapped]
    public List<Address> Addresses
    
        get  return AddressesJson == null ? AddressesDefault : JsonConvert.DeserializeObject<List<Address>>(AddressesJson ?? string.Empty); 
        set  AddressesJson = JsonConvert.SerializeObject(value); 
    
    [MaxLength(5000), JsonIgnore]
    public string AddressesJson  get; set; 
    [NotMapped]
    internal List<Address> AddressesDefault 
        get 
        
            var defaultAddress = new List<Address>();
            defaultAddress.Add(new Address()  Id = AddressId, Name = AddressName );
            return defaultAddress;
        
    

...

我会假设如果AddressesJson 支持字段为空,我会返回一个填充了一些默认值的新对象,这是有效的。但是当我执行 HTTP PUT 来更新 Addresses 字段(以及因此 AddressesJson 支持字段)时,它没有被设置并且总是返回 AddressesDefault

我错过了什么?有什么建议?非常感谢!

【问题讨论】:

您能否从您的控制器和存储库中添加更多代码?目前尚不清楚您执行操作的顺序。 有趣的是,如果我 PUT 到控制器(下面的示例),用户对象的 Addresses 属性始终是默认数据,而不是通过 HTTP PUT 发送的数据。 ' public async Task PutUser(int id, User user) if (!ModelState.IsValid) return BadRequest(ModelState); ` 【参考方案1】:

对不起我的英语。我没有评论的声誉,所以我会在答案部分发表评论:

第一点:当你使用Addresses getter 时,你已经在检查AddressesJson == null,所以你不需要调用AddressesJson ?? string.Empty,因为此时AddressesJson 永远不会为空。 你可以删除?? string.Empty

第二:你有没有在某个时候使用过Addresses.Add()? 请注意,当您使用 Addresses.Add(someAddress) 添加地址时,您的 AddressesJson 不会改变。 如果属实,在这种情况下,我推荐以下方法:

User 类中创建一个AddAddress() 方法。然后你可以更新AddressesJson
public void AddAddress(Address newAddress)

    // add to list
    Addresses.Add(newAddress);

    // updates json with new address added
    AddressesJson = JsonConvert.SerializeObject(Addresses);

希望我能帮上忙。

【讨论】:

第一句话 = ? 这只是复制/粘贴我尝试几种不同的方法来设置对象(如果它为空)。不会对最终结果产生影响。第二句话 = 谢谢,我试图避免这种情况,因为这意味着在 UI 方面进行大量重构,这是我试图避免的 ?

以上是关于EF6 设置默认属性禁用更改跟踪的主要内容,如果未能解决你的问题,请参考以下文章

将 EF6 配置为默认使用 varchar 而不是 nvarchar?

检测是不是禁用了 iOS 智能跟踪预防

EF 6 Codefirst - 使用流式 API 为基类中定义的属性设置默认值

在 EF6 中重新加载导航属性

代码优先迁移:如何为新属性设置默认值?

代码优先迁移中列的 EF6 Oracle 默认值