我有一个使用ASP.NET Web API 2和Entity Framework 6创建的REST API。我想序列化/反序列化对象并保留对其他对象的引用。
我已经在ASP.NET中定义了Tag模型类,该类还具有通过脚手架生成的香草控制器类:
// 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);
我正在使用requests和jsonPickle模块在Python中创建客户端。我有一个在Python中定义的等效类:
# Python
class Tag():
def __init__(self, jSrc=None):
#super(DBEntity,self).__init__()
self.ID = 0
self.Value = ""
self.Parent = None
if(jSrc != None):
self.__dict__ = jsonpickle.decode(jSrc)
以下Python代码可以正常工作,以便在“标签”表中创建标签条目:
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个新的Tag条目,而不是使用父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
数据库现在包含2个“父”标签,但是“子”标签的Parent_ID字段已正确设置为新创建的不正确的“父”标签。
我如何告诉ASP.NET系统查找父标记的ID并保留对原始标记的引用,而不仅仅是将父属性反序列化为新的标记条目?
答案 0 :(得分:0)
每个对ASP.NET的请求都应获得一个新的DbContext。这意味着,每次需要更新数据库时,都应检索要更新的记录,然后在SaveChanges
之前对其进行更新。
如果仅反序列化一个对象并保存更改,它将(如您所见)在数据库中创建新记录。
我建议您实现标准的3层机制,在API / Controller中使用视图模型,在业务层中使用DTO,在数据库层中使用实体(当前具有实体)。
简单(但我会建议错误)的修复程序将在您的控制器中执行以下操作:
public void MyAPI(ApiViewModel vm)
{
var entity = _dbContext.Find(tag.Id);
entity.Value = vm.Value;
_dbContext.SaveChanges();
return Ok();
}