Я ищу приложение Azure Mobile и настроил тестовый сервис и клиент.
Я настроить следующие Сущности сервис-сторона:
public class Hotel : EntityData
{
public string Title { get; set; }
public virtual ICollection<Booking> Bookings { get; set; }
}
public class Booking : EntityData
{
public BookingStatus BookingStatus { get; set; }
[ForeignKey("PersonId")]
public virtual Person Person { get; set; }
[ForeignKey("HotelId")]
public virtual Hotel Hotel { get; set; }
public string PersonId { get; set; }
public string HotelId { get; set; }
}
public class Person : EntityData
{
public string Name { get; set; }
public virtual ICollection<Booking> Bookings { get; set; }
}
И контроллер:
public class BookingController : TableController<Booking>
{
protected override void Initialize(HttpControllerContext controllerContext)
{
base.Initialize(controllerContext);
MobileServiceContext context = new MobileServiceContext();
DomainManager = new EntityDomainManager<Booking>(context, Request);
}
// GET tables/Booking/48D68C86-6EA6-4C25-AA33-223FC9A27959
public SingleResult<Booking> GetBooking(string id)
{
return Lookup(id);
}
// GET tables/Booking
public IQueryable<Booking> GetAllBookings()
{
return Query();
}
// PATCH tables/Booking/48D68C86-6EA6-4C25-AA33-223FC9A27959
public Task<Booking> PatchBooking(string id, Delta<Booking> patch)
{
return UpdateAsync(id, patch);
}
}
Я добавил некоторые данные по умолчанию с помощью CreateDatabaseIfNotExists<MobileServiceContext>
и когда я запуска и тестирования Web API , DB заполняется, и я рад, что ключи/отношения настроены правильно. Я только с помощью соглашения об именовании Code First (согласно this tutorial)
Я также создал тестовый клиент со следующими субъектами:
public class Person
{
public string Id { get; set; }
public byte[] Version { get; set; }
public string Name { get; set; }
public virtual ICollection<Booking> Bookings { get; set; }
}
public class Booking
{
public string Id { get; set; }
public byte[] Version { get; set; }
public BookingStatus BookingStatus { get; set; }
public string PersonId { get; set; }
public string HotelId { get; set; }
public virtual Person Person { get; set; }
public virtual Hotel Hotel { get; set; }
}
public class Hotel
{
public string Id { get; set; }
public byte[] Version { get; set; }
public string Title { get; set; }
public virtual ICollection<Booking> Bookings { get; set; }
}
И с этой тестовой логики:
using (var client = new MobileServiceClient(m_Url, new ODataParameterHandler())
{
client.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
client.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
var bookingTable = client.GetTable<Booking>();
var bookings = await placementTable
.Where(p => p.BookingStatus == BookingStatus.Confirmed && p.PersonId == 10)
.WithParameters(new Dictionary<string, string> { { "expand", "Hotel" } })
.ToListAsync();
var aBooking = bookings[0];
aBooking.BookingStatus = BookingStatus.Cancelled;
await bookingTable.UpdateAsync(aBooking);
}
// Class to allow $expand= querystring value to be passed in.
public class ODataParameterHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
UriBuilder builder = new UriBuilder(request.RequestUri);
builder.Query = builder.Query
.Replace("expand", "$expand")
.TrimStart('?');
request.RequestUri = builder.Uri;
return await base.SendAsync(request, cancellationToken);
}
}
GET/ToListAsync
работает нормально, и я получаю дочерний объект Hotel
, прикрепленный к моему Booking
. Однако Update
терпит неудачу с:
Сбой операции из-за конфликта: «Нарушение ограничения первичного ключа„PK_dbo.Hotels“. Невозможно вставить дубликат ключа в объект «dbo.Hotels». Дубликатное значение ключа (0e6e1bae-bd59-46ac-9630-a2b53dd04a90). \ R \ nПриложение завершено.
Но почему же он снова пытается включить мой дочерний объект INSERT? Во-первых, я не изменил его, а во-вторых, она имеет Id
, CreatedAt
и т.д.
я не могу найти какие-либо аналогичные вопросы, касающиеся Azure Mobile Apps, но я нашел this SO Post regarding Entity Framework но О.П. говорит о том, вручную создается детей, поэтому я не уверен, что он полностью применяется, поскольку я получил дочернюю сущность из БД через TableController
.
Я не знаком с Azure Mobile, но это выглядит как проблема с объектами, которые не имеют права «Entry.State» в контексте, те проблемы, которые возникают в отключенных сценариях. Похоже, что самый проголосовавший ответ в сообщении SO, на который вы ссылаетесь, исправит вашу проблему. Попробуйте установить дочерний элемент свойства 'aBooking.Hotel' в значение null перед выполнением' UpdateAsync' и оставить только значение «HotelId». – Diana