2017-08-22 6 views
0

DbContextとSaveChangesメソッドを使用してデータベースに挿入する、複雑で大きなオブジェクトグラフがあります。EF Core 2.0:オブジェクトグラフ内の正確なオブジェクトを検出すると、挿入操作でエラーが発生する

このオブジェクトは、40k行(約3MBのデータ)のテキストファイルを解析した結果です。このオブジェクトの中のいくつかのコレクションには何千ものアイテムがあります。

ファイルを正しく解析してコンテキストに追加して、オブジェクトの追跡を開始できるようにしました。しかし、SaveChangesにしようとすると、それは言う:

Microsoft.EntityFrameworkCore.DbUpdateException:エントリを更新中にエラーが発生しました。詳細については、内部例外を参照してください。 ---> System.Data.SqlClient.SqlException:文字列またはバイナリデータが切り捨てられます。

どのオブジェクトが問題を引き起こしているかを知るスマートで効率的な方法があるかどうかを知りたいと思います。 varcharフィールドがデータを格納するには小さすぎるようです。しかし、それは手動でチェックするテーブルとフィールドがたくさんあります。

もっと具体的なエラーを何とかしたいと思います。私は既にILoggerProviderを設定し、EnableSensitiveDataLoggingオプションをdbContextに追加して、どのsqlクエリが生成されているかを確認することができました。パラメータ値がdbContextによって生成されたログに存在しないため、パラメータ値を表示できるように、MiniProfilerを追加しました。

Webのどこかを読んで、私はEF6でSQLがデータベースに渡されて実行される前にいくつかの検証が行われていることを発見しました。しかし、EFコアでこれはもう利用できないようです。どうすればこの問題を解決できますか?

答えて

0

これを解決するために私が見つけた唯一のアプローチは、dbContextのSaveChangesメソッドをオーバーライドすることによっていくつかの検証を実装することです。

Implementing Missing Features in Entity Framework Core - Part 3

Validation in EF Core

結果は...

ApplicationDbContext.cs

public override int SaveChanges(bool acceptAllChangesOnSuccess) 
    { 
     ValidateEntities(); 

     return base.SaveChanges(acceptAllChangesOnSuccess); 
    } 

    public override async Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = new CancellationToken()) 
    { 
     ValidateEntities(); 

     return await base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); 
    } 

    private void ValidateEntities() 
    { 
     var serviceProvider = this.GetService<IServiceProvider>(); 
     var items = new Dictionary<object, object>(); 

     var entities = from entry in ChangeTracker.Entries() 
         where entry.State == EntityState.Added || entry.State == EntityState.Modified 
         select entry.Entity; 

     foreach (var entity in entities) 
     { 
      var context = new ValidationContext(entity, serviceProvider, items); 
      var results = new List<ValidationResult>(); 

      if (Validator.TryValidateObject(entity, context, results, true)) continue; 

      foreach (var result in results) 
      { 
       if (result == ValidationResult.Success) continue; 

       var errorMessage = $"{entity.GetType().Name}: {result.ErrorMessage}"; 
       throw new ValidationException(errorMessage); 
      } 
     } 
    } 

:私は、これら2つのアプローチのマージが鉱山を構築するために作られました他のSaveChangesオーバーロードをオーバーライドする必要はないことに注意してください。これらの2つを呼び出します。

0

エラーは、保持できる以上の文字をフィールドに書き込んでいることを示します。 このエラーは、NVARCHAR(4)またはCHAR(4)として特定のフィールドを作成し、そのフィールドに「hello」を書き込むとスローされます。

これで、読み込んだ値の長さを確認して、問題の原因となっている値を見つけることができます。少なくともフィールドには長すぎるものがあります。

関連する問題