Azure AppService-モバイルでコントローラーを実行しています。トレースは、db.SaveChanges()
これが失敗するまで、以下のコードが正常に実行されることを示しています。
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);
}
}
appserviceの診断からのスタックトレース(残念ながら私は理解していません)は次のようになります。
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()
だから私はこれを試してみます、それはより詳細なエラーメッセージを与えるでしょう:
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);
}
}
}
また
私はあってはならない分野があることを確認するためにすべての設定を通過しますnull
ですnull
に従ってとしてのstackoverflow上でこの答え。
例外は、Id
フィールドが必須であることを隠します。これは例外です。
私が使用しているデータベースEntityData
(ここではmsdnで説明されています)の出所Id
。MobileServiceでの私の使用はId
、行を実行したときに作成されたものでしたが、失敗しましたdb.SaveChanges()
。誰かがこれを明確にすることができますか?クラスは次のようになります。
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; }
}
EFでは文字列主キーの自動生成サポートはありません。そのため、手動で主キーを割り当てる必要があります。
コンストラクターを使用してId
、CreatedDate
を初期化できUpdatedDate
ます。
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; }
}
コンテキストでsavechangesメソッドをオーバーライドできます。エンティティを変更すると、このメソッドはupdateddateを自動的に変更します。
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();
}
編集:最初の解決策は、どのライブラリでも実現されていない一般的な解決策でした。
serilazationに必要なEntityData。モバイルクライアントとバックエンドサーバーが相互に通信しようとする場合、このクラスが役立ちます。たとえば、モバイルクライアントはナビゲーションプロパティをサポートしていませんが、バックエンドサーバーはサポートしています。entitydataをセリライジングすると、これらのプロパティが非表示になります。
このアプリ用にデータベースを設計する場合。このドキュメントに従ってください。
まずEntityData
、ライブラリ内にあるクラスを使用する必要があります。モデルは、EntityData
クラスではなく、モデルから継承する必要があります。
2番目:オーバーライドモデルの作成時に、コンテキストにこのコードが含まれている必要があります。作成/更新されたatとIdの自動更新にこれが必要です(これがあなたの質問に対する答えです)。
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()));
}
すでに存在するデータベースを使用する場合は、このドキュメントに従ってください。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加