5

Ich habe einen Controller auf Azure App Service - Mobile ausgeführt. Die Ablaufverfolgung zeigt, dass der folgende Code einwandfrei funktioniert, bis db.SaveChanges() dies fehlschlägt.Db Kontext auf azure App Service (Handy) schlägt fehl

var telemetry = new Microsoft.ApplicationInsights.TelemetryClient(); 
telemetry.TrackTrace("Create User"); 
using (BCMobileAppContext db = new BCMobileAppContext()) 
{ 
    string Username_NoSpaces = username.Username.Replace(" ", ""); 
    var user = db.Users.FirstOrDefault(u => u.Username_NoSpaces == Username_NoSpaces || u.MicrosoftToken == this.User.Identity.Name); 
    telemetry.TrackTrace("1"); 
    if (user == null && !Username_NoSpaces.Contains(",")) 
    { 
      telemetry.TrackTrace("2"); 
      DateTime now = DateTime.UtcNow; 
      telemetry.TrackTrace("3"); 
      string username_noSpaces = username.Username.Replace(" ", ""); 
      DataObjects.User userItem = new DataObjects.User() { Created = now, UserId = this.User.Identity.Name, MicrosoftToken = this.User.Identity.Name, Username_NoSpaces = username_noSpaces, Update = now, Username = username.Username, Gold = 1, Level = 1, Title = "Sir", InGameCrest = "", ReceiveNotifications = true }; 
      telemetry.TrackTrace("4"); 
      UserDTO returnObject1 = new UserDTO() { Created = userItem.Created, isCreated = true, MicrosoftId = userItem.MicrosoftToken, Username = userItem.Username }; 
      telemetry.TrackTrace("5"); 
      db.Users.Add(userItem); 
      telemetry.TrackTrace("6"); 
      db.SaveChanges();   //Trace and code fails 
      telemetry.TrackTrace("7"); 
      UserDTO returnObject = new UserDTO() { Created = userItem.Created, isCreated = true, MicrosoftId = userItem.MicrosoftToken, Username = userItem.Username }; 
      telemetry.TrackTrace("8"); 
      return Ok(returnObject); 
     } 
} 

Der Stacktrace aus dem Diagnose auf dem appservice gibt (was ich leider nicht verstehen):

2016-04-07T17:29:19 PID[5008] Error  Operation=ReflectedHttpActionDescriptor.ExecuteAsync, Exception=System.Data.Entity.Validation.DbEntityValidationException: Validation failed for one or more entities. See 'EntityValidationErrors' property for more details. 
    at System.Data.Entity.Internal.InternalContext.SaveChanges() 
    at System.Data.Entity.Internal.LazyInternalContext.SaveChanges() 
    at System.Data.Entity.DbContext.SaveChanges() 
    at BCMobileAppService.Controllers.Test2Controller.Post(UserDTO username) in C:\Users\johann\Desktop\BCMobileApp_Runtime\BCMobileAppService\Controllers\TestController.cs:line 78 
    at lambda_method(Closure , Object , Object[]) 
    at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters) 
    at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments) 
    at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary 2 arguments, CancellationToken cancellationToken) 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Web.Http.Tracing.ITraceWriterExtensions.<TraceBeginEndAsyncCore>d__18 1.MoveNext() 
2016-04-07T17:29:19 PID[5008] Error  Operation=ApiControllerActionInvoker.InvokeActionAsync, Exception=System.Data.Entity.Validation.DbEntityValidationException: Validation failed for one or more entities. See 'EntityValidationErrors' property for more details. 
    at System.Data.Entity.Internal.InternalContext.SaveChanges() 
    at System.Data.Entity.Internal.LazyInternalContext.SaveChanges() 
    at System.Data.Entity.DbContext.SaveChanges() 
    at BCMobileAppService.Controllers.Test2Controller.Post(UserDTO username) in C:\Users\johann\Desktop\BCMobileApp_Runtime\BCMobileAppService\Controllers\TestController.cs:line 78 
    at lambda_method(Closure , Object , Object[]) 
    at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters) 
    at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments) 
    at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary 2 arguments, CancellationToken cancellationToken) 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Web.Http.Tracing.ITraceWriterExtensions.<TraceBeginEndAsyncCore>d__18 1.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Web.Http.Tracing.ITraceWriterExtensions.<TraceBeginEndAsyncCore>d__18 1.MoveNext() 
2016-04-07T17:29:19 PID[5008] Error  Operation=Test2Controller.ExecuteAsync, Exception=System.Data.Entity.Validation.DbEntityValidationException: Validation failed for one or more entities. See 'EntityValidationErrors' property for more details. 
    at System.Data.Entity.Internal.InternalContext.SaveChanges() 
    at System.Data.Entity.Internal.LazyInternalContext.SaveChanges() 
    at System.Data.Entity.DbContext.SaveChanges() 
    at BCMobileAppService.Controllers.Test2Controller.Post(UserDTO username) in C:\Users\johann\Desktop\BCMobileApp_Runtime\BCMobileAppService\Controllers\TestController.cs:line 78 
    at lambda_method(Closure , Object , Object[]) 
    at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.< >c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters) 
    at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments) 
    at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary 2 arguments, CancellationToken cancellationToken) 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Web.Http.Tracing.ITraceWriterExtensions.<TraceBeginEndAsyncCore>d__18 1.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Web.Http.Tracing.ITraceWriterExtensions.<TraceBeginEndAsyncCore>d__18 1.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__5.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__5.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__0.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Web.Http.Tracing.Tracers.HttpControllerTracer.<ExecuteAsyncCore>d__5.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Web.Http.Tracing.ITraceWriterExtensions.<TraceBeginEndAsyncCore>d__18 1.MoveNext() 

aktualisieren

Also werde ich versuchen, this, die genauere Fehlermeldung geben wird:

catch (DbEntityValidationException dbEx) 
{ 
foreach (var validationErrors in dbEx.EntityValidationErrors) 
{ 
    foreach (var validationError in validationErrors.ValidationErrors) 
    { 
     Trace.TraceInformation("Property: {0} Error: {1}", 
           validationError.PropertyName, 
           validationError.ErrorMessage); 
    } 
} 
} 

Auch

Ich werde die alle Einstellungen durchlaufen, um sicherzustellen, dass das ein Feld, das null nicht null wie nach this answer on stackoverflow ist sein muss.

Testen der oben

Die Ausnahme versteckt, dass die Id Feld erforderlich ist, ist die Ausnahme.

Die Datenbank, die ich verwende EntityData (beschrieben here on msdn), wo die Id stammt. Meine Verwendung auf MobileService war, dass die Id erstellt wurde, wenn ich die Zeile ausgeführt habe, die db.SaveChanges() fehlschlägt. Kann jemand das klären? Die Klasse sieht wie folgt aus:

public abstract class EntityData : ITableData 
{ 
    protected EntityData(); 

    [Index(IsClustered = true)] 
    [TableColumn(TableColumnType.CreatedAt)] 
    public DateTimeOffset? CreatedAt { get; set; } 
    [TableColumn(TableColumnType.Deleted)] 
    public bool Deleted { get; set; } 
    [TableColumn(TableColumnType.Id)] 
    public string Id { get; set; } 
    [TableColumn(TableColumnType.UpdatedAt)] 
    public DateTimeOffset? UpdatedAt { get; set; } 
    [TableColumn(TableColumnType.Version)] 
    public byte[] Version { get; set; } 
} 
+0

Sie haben immer noch den Fehler nach dem Durchlaufen der Einstellungen, die Sie oben erwähnt haben? –

+0

@RamiSarieddine Ich habe jetzt alles getestet und ein Update zu der Frage geschrieben, es ist das 'Id' Feld von' EntityData' das die 'Exception' gibt. Ich hatte das Verständnis von früheren Arbeiten, dass dies erstellt wurde, als ich 'db.SaveChanges()', das ist die Zeile, die bei der Ausführung fehlschlägt. Weißt du warum das so ist? Ich habe 'EntityData' vorher noch nicht benutzt, aber wegen der Spalten' CreatedAt' und 'UpdatedAt', die automatisch aktualisiert würden? – JTIM

+0

@AlexanderDerck Nein, also folgernd von Ihnen: Meine Klasse, die von 'EntityData' erbt, sollte eine Variable haben: [DatabaseGenerated (DatabaseGeneratedOption.Identity)] public string Id {get; set;} 'als kompatibel mit dem Typ aus' EntityData', oder? – JTIM

Antwort

3

Es gibt keine automatische Unterstützung Primärschlüssel in EF für String erzeugen. Deshalb sollten Sie Ihren Primärschlüssel manuell zuweisen.

Sie können Id, und UpdatedDate mit Konstruktor initialisieren.

public abstract class EntityData : ITableData 
    { 
    //Change the constructor to initilaize required filled with meaningful data. 
     protected EntityData() 
     { 
      Id=Guid.NewGuid().ToString(); 
      CreatedDate=DateTime.UtcNow; 
      UpdatedDate=DateTime.UtcNow; 
     } 

     [Index(IsClustered = true)] 
     [TableColumn(TableColumnType.CreatedAt)] 
     public DateTimeOffset? CreatedAt { get; set; } 
     [TableColumn(TableColumnType.Deleted)] 
     public bool Deleted { get; set; } 
     [TableColumn(TableColumnType.Id)] 
     public string Id { get; set; } 
     [TableColumn(TableColumnType.UpdatedAt)] 
     public DateTimeOffset? UpdatedAt { get; set; } 
     [TableColumn(TableColumnType.Version)] 
     public byte[] Version { get; set; } 
    } 

Sie können die Savechanges-Methode in Ihrem Kontext überschreiben. Wenn Sie eine Entität geändert haben, ändert diese Methode das Aktualisierungsdatum automatisch.

public override int SaveChanges() 
    { 
     //Get Modified Entities 
     var modifiedEntries = ChangeTracker.Entries() 
      .Where(x => x.Entity is ITableData 
       && (x.State == EntityState.EntityState.Modified)); 
     foreach (var entry in modifiedEntries) 
     { 
      var entity = entry.Entity as ITableData; 
      //Modify updateddate 
      if (entity != null) 
      { 
       entity.UpdatedDate = DateTime.UtcNow; 
      } 
     } 
     return base.SaveChanges(); 
    } 

bearbeiten: Die erste Lösung war allgemeine Lösung, die mit jeder Bibliothek nicht realeted wird.

EntityData Sie für die Serilisierung benötigen. Wenn der mobile Client und der Backend-Server miteinander kommunizieren möchten, hilft Ihnen diese Klasse weiter. Zum Beispiel unterstützt der mobile Client keine Navigationseigenschaften, der Backend-Server jedoch. Wenn Sie Entitätsdaten serilisieren, werden diese Eigenschaften für Sie ausgeblendet.

Wenn Sie Ihre Datenbank für diese App entwerfen. Befolgen Sie diese document.

Erstens: Sie sollten EntityData Klasse innerhalb der Bibliothek verwenden. Ihre Modelle sollten davon nicht Ihre EntityData Klasse erben.

Zweitens: Ihr Kontext sollte diesen Code beim Erstellen von Override-Modellen haben. Sie benötigen dies für die automatische Aktualisierung von erstellt/aktualisiert um und Id (Dies ist die Antwort für Ihre Frage).

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
     { 
      string schema = ServiceSettingsDictionary.GetSchemaName(); 
      if (!string.IsNullOrEmpty(schema)) 
      { 
       modelBuilder.HasDefaultSchema(schema); 
      } 

      modelBuilder.Conventions.Add(
       new AttributeToColumnAnnotationConvention<TableColumnAttribute, string>(
        "ServiceTableColumn", (property, attributes) => attributes.Single().ColumnType.ToString())); 
     } 

Wenn Sie eine Datenbank verwenden, die bereits vorhanden ist, wird dieses document folgen.

+0

Okay, also ist es normal, die Funktion zu überschreiben? Wenn ja wo in der Lösung sollte ich das setzen, in den Controller oder? – JTIM

+1

In 'BCMobileAppContext' –

+0

Okay, ich werde das heute Abend versuchen! – JTIM

Verwandte Themen