使用 v4 的 OData 客户端 (.NET) 创建/发布新实体时,我们不会从服务中获取自动生成(自动递增)的 ID/密钥。当我们创建新实体时,我们没有分配 ID(它是一个"int",因此值为"0")。调用 SaveChanges 后,结果 JSON 响应具有新的自动分配 ID(例如"4662")。问题是客户端上的实体的 ID 仍然为"0"(它没有映射回原始实体)。
我还在GitHub上打开了这个问题:https://github.com/OData/odata.net/issues/775
受影响的程序集
- Microsoft.数据.OData - v5.7.0
- Microsoft.OData.Client - v6.15.0
- Microsoft.OData.Core - v6.15.0
- Microsoft.OData.Edm - v6.15.0
重现步骤
- 保存将在服务器端自动分配 ID 的新实体(不要在客户端设置此 ID)
- 保存后,检查新实体上的 ID 属性(在客户端)
预期成果
新创建(并保存)的实体将更新 ID,以匹配返回到客户端的服务器端响应 (JSON)。
实际结果
来自服务器端的 JSON 响应具有正确的 ID,但客户端上的实体永远不会使用此新信息进行更新。
为了支持你的方案,需要满足一些要求。 有关完整参考,请参阅我在 GitHub 上的示例项目。
给定一个模型:
public class Item {
[Key] //define as key
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] //used by EF to auto generate Ids and mapping them back on inserts
public int Id { get; set; }
[Required(AllowEmptyStrings = false)]
public string Name { get; set; }
}
A EntityFramwork-DbContext:
public class SampleContext : DbContext {
public SampleContext()
: base("name=SampleContext") {
}
public DbSet<Person> Persons { get; set; }
public DbSet<Item> Items { get; set; }
}
直接的 OData 配置:
var builder = new ODataConventionModelBuilder();
builder.EntitySet<Person>("Persons");
builder.EntitySet<Item>("Items");
config.MapODataServiceRoute("ODataRoute", "odata", builder.GetEdmModel());
和相应的 ODataController:
public class ItemsController : ODataController {
private readonly SampleContext _Db;
public ItemsController() {
_Db = new SampleContext();
}
...
[ResponseType(typeof(CreatedODataResult<Item>))]
public IHttpActionResult Post(Item p) {
if (!ModelState.IsValid)
return BadRequest(ModelState);
var inserted = _Db.Items.Add(p);
_Db.SaveChanges();
//return entity with any server side changes. This would also work for other DB-generated columns.
return Created(inserted);
}
}
应产生所需的结果:
public void AddingItemTransportsServerGeneratedIdBackToClientSideModel() {
var item = new Item() {
Name = Guid.NewGuid().ToString()
};
var container = new Container(new Uri("http://localhost/ODataAutoId/odata"));
container.AddToItems(item);
container.SaveChanges();
var actual = item.Id;
var unexpected = 0;
Assert.AreNotEqual(unexpected, actual);
}
您的实际实现可能会有所不同或错过某些要求。为了在您的特定场景中提供帮助,请提供更多详细信息,如我的评论中所述。