我正在使用Web API2和EF6代码开始使用Rest API,首先从http://www.asp.net/web-api/overview/data/using-web-api-with-entity-framework/part-4上的指南开始 我基本上做同样的事情有多对多的关系,当我创建一个对象时,我们称之为A,我在帖子中包含一个B对象数组作为Bs变量。它们都是在初始帖子中按预期创建的,但是当我添加第二个对象A时,它应该链接到与第一个对象A相同的一个或多个B,而不是匹配现有的B尝试创建新的B,但是B的名称有一个限制,这不会起作用。我如何确保它不会尝试每次创建一个新对象B,而是链接到现有的对象B(如果有的话)?
以下是更详细的示例。
我有两个模型,我们称它们为A和B.它们有多对多的关系
public class A
{
public int Id { get; set; }
[Required, StringLength(100), Index("IDX_Name", 2, IsUnique = true)]
public string Name { get; set; }
[StringLength(300)]
public string Description { get; set; }
public ICollection<B> Bs{ get; set; }
}
模型B
public class B
{
public int Id { get; set; }
[Required, StringLength(100), Index("IDX_Name", 2, IsUnique = true)]
public string Name { get; set; }
public ICollection<B> As{ get; set; }
}
我不包括自动生成的上下文。 并且在自动生成的Controller脚手架中,对于模型A的Web API POST方法,它看起来像这样
[ResponseType(typeof(A))]
public async Task<IHttpActionResult> PostGame(A a)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.As.Add(a);
await db.SaveChangesAsync();
return CreatedAtRoute("DefaultApi", new { id = a.Id }, a);
}
所有表格都创建得很好,如果我在第一篇文章中使用以下json创建我的第一个对象:
{
"Name": "FirstA",
"Description": "FirstADesc",
"Bs" : [{"Name":"FirstB"}]
}
它可以工作,并且创建了FirstA和FirstB。 如果我然后发布一个也与FirstB obect链接的SecondA
{
"Name": "SecondA",
"Description": "SecondADesc",
"Bs" : [{"Name":"SecondB"},{"Name":"FirstB"}]
}
它将取代找到FirstB尝试再次创建它。这是由于约束。
我的第一个猜测是我应该在第二篇文章中使用ID:s。像:
{
"Name": "SecondA",
"Description": "SecondADesc",
"Bs" : [{"Id":"1"},{"Name":"FirstB"}]
}
但这也不起作用。
实现此目的的唯一方法是从控制器替换脚手架代码并手动检查Bs中的每个对象(如果已存在)?
基本上它是“标记到帖子问题”...... 我已经查看了Attached vs Detached Data主题并阅读了有关此事的文章,但没有找到答案,我可以理解这是否可以通过一些正确的注释自动完成,或者是否必须在控制器中“手动”完成。
提前致谢!
答案 0 :(得分:0)
对此没有太多回应, 结束循环并手动检查现有条目,如下所示。
[ResponseType(typeof(A))]
public async Task<IHttpActionResult> PostGame(A a)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
foreach (var asd in a.Bs.ToList())
{
var t = db.Bs.FirstOrDefault(a => a.Name == asd.Name);
if (t != null)
{
a.Bs.Remove(asd);
a.Bs.Add(t);
}
}
db.As.Add(a);
await db.SaveChangesAsync();
return CreatedAtRoute("DefaultApi", new { id = a.Id }, a);
}
不能让人觉得必须有更好的方法。