Как опубликовать сущность в конечной точке OData, одновременно связывая ее с другими существующими сущностями в теле?
Рассмотрим следующую структуру класса (образец):
class Invoice
{
public int Id { get; set; }
public Person Issuer { get; set; }
public Person Recipient { get; set; }
// other properties
}
class Person
{
public int Id { get; set; }
// other properties
}
И Invoice
, и Person
являются сущностями в моем домене (таким образом, свойство Id
). Представьте, что оба экспонируются в своих собственных наборах сущностей, поэтому:
GET http://host/odata/People(1)
возвращает Person
с Id = 1
GET http://host/odata/Invoices(2)?$expand='Issuer, Recipient'
возвращает Invoice
с Id = 2
и расширениями Issuer
и Recipient
в полезной нагрузке
Теперь рассмотрим следующее требование :
Я хочу создать в системе новый счет, который будет связан с существующим эмитентом и получателем
Как мне "сообщить" платформе OData, что я Хотите связать данное свойство навигации с существующим объектом? Как бы моё действие контроллера было уведомлено, что это намерение?
В идеале, я бы хотел, чтобы тело POST выглядело так:
POST http://host/odata/Invoices
{"Issuer": "/ odata / People (1)", "Recipient": "/ odata / People (2)", "Property1": "someValue", "Property2": "100",. ..}
Как только сервер получит эту полезную нагрузку, он должен:
- Загрузить необходимые "people (1)"
Person
для Issuer
имущество. Если он не существует, должен быть возвращен неверный запрос. - Загрузите необходимые "people (2)"
Person
для свойства Recipient
. Если он не существует, должен быть возвращен неверный запрос. - Создайте новый
Invoice
экземпляр и назначьте Issuer
и Recipient
сверху, а затем сохраните его в базе данных.
Я знаю, что OData имеет поддержку для последующей настройки отношений со специальными URL-адресами PUT / POST с использованием синтаксиса entity/relation/$ref
. С таким синтаксисом я мог бы сделать что-то вроде этого:
POST http://host/odata/Invoices
{ "Property1": "someValue", "Property2": "100" }
PUT http://host/odata/Invoices(x)/Issuer/$ref
{"@odata.id":"http://host/odata/People(1)"}
PUT http://host/odata/Invoices(x)/Recipient/$ref
{"@odata.id":"http://host/odata/People(2)"}
Однако Я хочу иметь возможность выполнить все это в одной операции POST, которая должна атомарно создать экземпляр.
Я попробовал несколько идей, чтобы увидеть, что сервер примет, и это, казалось, go через:
{
"Issuer": { "@odata.id": "/odata/People(1)" },
"Recipient": { "@odata.id": "/odata/People(2)" },
"Property1": "someValue",
"Property2": "100",
...
}
Но я понятия не имею, как я смогу читать / анализировать идентификаторы из этого (например, как это делается в выделенном методе Ref
), или даже если это поддерживается в стандарт OData.
Сейчас я прибегну к простой передаче свойства ID
в модели и на сервере, предполагая, что это всегда будет означать существующие отношения, но это далеко от идеала, поскольку это не так. достаточно универсальный и сделает мой API негибким.