C# 在ASP.NET Web API 2中,如何跨JSON序列化保留对象引用?

C# 在ASP.NET Web API 2中,如何跨JSON序列化保留对象引用?,c#,asp.net,python-2.7,asp.net-web-api2,C#,Asp.net,Python 2.7,Asp.net Web Api2,我使用ASP.NET Web API 2和Entity Framework 6创建了一个REST API。我想序列化/反序列化对象并保留对其他对象的引用 我在ASP.NET中定义了一个标记模型类,它还有一个通过脚手架生成的普通控制器类: // C# // Tag.cs public class Tag { public int ID { get; set; } public string Value { get; set; } public Tag Parent { ge

我使用ASP.NET Web API 2和Entity Framework 6创建了一个REST API。我想序列化/反序列化对象并保留对其他对象的引用

我在ASP.NET中定义了一个标记模型类,它还有一个通过脚手架生成的普通控制器类:

// C#
// Tag.cs
public class Tag
{
    public int ID { get; set; }
    public string Value { get; set; }
    public Tag Parent { get; set; } // I know this can't be circular 
}

...

// Context.cs
...
public DbSet<Tag> Tag { get; set; }
...
modelBuilder.Entity<Tag>().HasOptional(_ => _.Parent);
以下Python代码可以正确地在Tags表中创建标记条目:

newTag = Tag()
newTag.Value = "Parent"
headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
r = requests.post("http://server/api/Tags", data=jsonpickle.encode(newTag), headers=headers)


# ID | Value  | Parent_ID
# 1  | Parent | -
但是,当我将父标记指定给设置了正确ID的标记对象时,将创建2个新标记条目,而不是使用父ID引用:

# Get Tag
rg = requests.get("http://server/api/Tags/1")
parentTag = Tag(rg.text)

# Create new Tag with Parent reference
newTag = Tag()
newTag.Value = "Child"
headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
r = requests.post("http://server/api/Tags", data=jsonpickle.encode(newTag), headers=headers)

# ID | Value  | Parent_ID
# 1  | Parent | -
# 2  | Parent | - << This should net be created
# 3  | Child  | 2 << This should be 1
#获取标签
rg=请求。获取(“http://server/api/Tags/1")
parentTag=Tag(rg.text)
#创建具有父引用的新标记
newTag=Tag()
newTag.Value=“Child”
headers={'Content-type':'application/json','Accept':'text/plain'}
r=请求。post(“http://server/api/Tags,data=jsonpickle.encode(newTag),headers=headers)
#ID |值|父项| ID
#1 |家长|-

#2 | Parent |-对ASP.NET的每个请求都应该获得一个新的DbContext。这意味着每次需要更新数据库时,都应该在
SaveChanges
之前检索要更新的记录,然后对其进行更新

如果您只是反序列化一个对象并保存更改,它将(如您所见)在数据库中创建一个新记录

我建议您实现一个标准的三层机制,在API/Controller中使用视图模型,在业务层使用DTO,在数据库层使用实体(您当前拥有的实体)

简单的(但我建议是错误的)修复方法是在控制器中执行以下操作:

public void MyAPI(ApiViewModel vm) 
{
 var entity = _dbContext.Find(tag.Id);
 entity.Value = vm.Value;
 _dbContext.SaveChanges();
 return Ok();
}
public void MyAPI(ApiViewModel vm) 
{
 var entity = _dbContext.Find(tag.Id);
 entity.Value = vm.Value;
 _dbContext.SaveChanges();
 return Ok();
}