2015-08-24 3 views
3

В моем Azure Mobile Service У меня есть класс контроллера UserController : TableController<User> и в нем метод прибудет:Добавить в контроллере Azure Mobile Services

// GET tables/User/48D68C86-6EA6-4C25-AA33-223FC9A27959 
public SingleResult<User> GetUser(string id) 
{ 
    return Lookup(id); 
} 

Я хочу записывать каждый раз, когда пользователь доступа и так добавить простой тип модели:

public class UserVisit : Microsoft.WindowsAzure.Mobile.Service.EntityData 
{ 
    public string VisitingUser { get; set; } 
    public DateTime TimeOfVisit { get; set; } 
} 

и включает в себя свойство public DbSet<UserVisit> UserVisits { get; set; } в моем VCollectAPIContext : DbContext классе (и обновление базы данных с кодовой первой миграцией).

Чтобы добавить UserVisit в базу данных, когда идентификатор пользователя запрашивается меняю мой метод контроллера для

// GET tables/User/48D68C86-6EA6-4C25-AA33-223FC9A27959 
public async Task<SingleResult<User>> GetUser(string id) 
{ 
    var userVisit = new UserVisit { VisitingUser = id, TimeOfVisit = DateTime.UtcNow }; 
    context.UserVisits.Add(userVisit); 
    await context.SaveChangesAsync(); 
    return Lookup(id); 
} 

Но SaveChangesAsync терпит неудачу с System.Data.Entity.Validation.DbEntityValidationException. Копаясь в свойстве EntityValidationErrors исключения, я обнаружил, что проблема в том, что «поле« Идентификатор »требуется».

Это немного странно. Поле Id является одним из свойств базового класса Microsoft.WindowsAzure.Mobile.Service.EntityData, который я ожидал бы добавить автоматически при вставке. Независимо от того, что я могу добавить его и несколько свойств другого базового класса в таким образом:

// GET tables/User/48D68C86-6EA6-4C25-AA33-223FC9A27959 
public async Task<SingleResult<User>> GetUser(string id) 
{ 
    var userVisit = new UserVisit { Id = Guid.NewGuid().ToString(), Deleted = false, VisitingUser = id, TimeOfVisit = DateTime.UtcNow, CreatedAt = DateTimeOffset.Now }; 
    context.UserVisits.Add(userVisit); 
    await context.SaveChangesAsync(); 
    return Lookup(id); 
} 

На этот раз я получаю System.Data.Entity.Infrastructure.DbUpdateException, потому что «не удается вставить значение NULL в столбец" CreatedAt». Это не было нулевым при вызове Add. Таким образом, CreatedAt был установлен на нуль где-то вне моего кода, а затем в результате не получается вставка!

Я также попытался создать переменную EntityDomainManager<UserVisit> userVisitDomainManager; экземпляра в инициализаторе контроллера, а затем переписывание мой контроллер метод получить как

// GET tables/User/48D68C86-6EA6-4C25-AA33-223FC9A27959 
public async Task<SingleResult<User>> GetUser(string id) 
{ 
    var userVisit = new UserVisit { VisitingUser = id, TimeOfVisit = DateTime.UtcNow }; 
    await userVisitDomainManager.InsertAsync(userVisit); 
    return Lookup(id); 
} 

Это терпит неудачу с таким же сообщением «Не удается вставить значение NULL в столбец«CreatedAt '"

Как выполнить, казалось бы, простую задачу вставки связанного элемента данных в мой метод контроллера?

+0

Как выглядит таблица UserVisit в базе данных? Интересно, проблема в том, что мобильные службы SqlGenerator не запускались. Поведение, которое вы описываете context.UserVisits.Add(), очень странно! –

+1

Попробуйте выполнить регистрацию созданных SQL-операторов: https://msdn.microsoft.com/en-us/data/dn469464.aspx#Log –

ответ

2

Решение, вероятно, похоже на this answer. Я предполагаю, что ваша миграция не использует SqlGenerator Mobile Services, поэтому некоторые пользовательские настройки SQL не применяются. Это означает, что:

  • Идентификатор не получает значение по умолчанию NEWID() - это объясняет вашу ошибку «Id field required».
  • CreatedAt не получает значение по умолчанию SYSUTCDATETIME() - это в сочетании с атрибутом [DatabaseGenerated] на EntityData.CreatedAt объясняет ошибку «NULL CreatedAt».

Попробуйте обновить свою миграцию в соответствии со ссылкой выше и посмотреть, будет ли это работать для вас.

+0

Спасибо, Бретт. Я попробую это. Как я могу заставить свою миграцию использовать Mobile SqlGenerator? – dumbledad

+0

Посмотрите ссылку в моем ответе выше - она ​​показывает вам следующее: 'SetSqlGenerator (« System.Data.SqlClient », новый EntityTableSqlGenerator());' – brettsam

+0

У меня не было возможности проверить это, поскольку я погряз в другие ошибки сервера, которые мне нужно перемещаться, но я буду награждать награду в любом случае до того, как она закончится, так как это выглядит обнадеживающим. – dumbledad

1

Чтобы устранить проблему «поля Идентификатор требуется», следуя инструкциям brettsam «s.

Добавьте это в модели:

[Key] 
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
[TableColumn(TableColumnType.Id)] 
public new string Id { get; set; } 

Он будет автоматически генерировать GUID при добавлении объекта.

+0

Это выглядит неправильно. Как уже упоминалось в вопросе, мои классы моделей наследуют от [Microsoft.WindowsAzure.Mobile.Service.EntityData] (https://msdn.microsoft.com/en-us/library/microsoft.windowsazure.mobile.service.entitydata.aspx) который предоставляет свойство «Id» (между прочим). Несомненно, что генерирует GUID? – dumbledad

+1

Согласен, но он не генерирует GUID в моих тестах, когда у меня была начальная миграция с помощью SetSqlGenerator («System.Data.SqlClient», новый EntityTableSqlGenerator()); –

+1

Спасибо, Доминик, это полезно. Я думаю, что когда я переопределяю методы SDK, потому что они не могут решить вопрос с помощью SDK. В настоящее время я изучаю переписывание своего серверного кода в ASP.Net API 2 с помощью Entity Framework, но без Azure Mobile Services. – dumbledad

Смежные вопросы