2017-10-29 5 views
2

EF 6.1からEF Core 2.0への移行の一環として、同時実行トークンが同じように動作するかどうかを確認するための簡単なテストを追加しました。しかし、これは基になるデータベースプロバイダに依存していることに注意してください:SqlServerでは機能しますが、MS InMemoryデータベースでは機能しません。Microsoft.EntityFrameworkCore.InMemoryを使用して並行性トークンをテストする

エンティティクラスは非常に単純です:

public class AcademicTermDate 
{ 
    public int AcademicTermDateID { get; set; } 

    public DateTime StartDate { get; set; } //but no end date, because it's derived in controcc and rederived here. 

    public bool Deleted { get; set; } 

    [Timestamp] 
    public byte[] RowVersion { get; set; } 
} 

それを作成するコードも簡単です:私は、コードを以下のとおりに古いプレーンなSQL Serverを使用している場合

 using (var context = _factory.CreateDbContext(null)) 
     { 
      var term = new AcademicTermDate(); 
      term.StartDate = new DateTime(2001, month, 1); 
      context.AcademicTermDate.Add(term); 

      context.SaveChanges(); 
     } 

は、興味深いです:

public MyContext CreateDbContext(string[] args) 
    { 
     var builder = new DbContextOptionsBuilder<MyContext>(); 

     var connectionString = "server=.\\sql2012;Database=CA15;Trusted_Connection=True;"; 
     builder.UseSqlServer(connectionString); 

     return new MyContext(builder.Options); 
    } 

期待どおりに動作します。 on context.SaveChanges()RowVersionを読み込むことができます。

ただし、私のテストで使用するように思われるInMemoryデータベースプロバイダを使用した場合、RowVersionはnull値(つまり初期化されていません)のまま残ります。後者の場合

は、工場出荷時は次のように定義されます

public MyContext CreateDbContext(string[] args) 
    { 
     var builder = new DbContextOptionsBuilder<MyContext>(); 

     builder.UseInMemoryDatabase(databaseName: "InMemory"); 

     return new MyContext(builder.Options); 
    } 

私は私が提供しなければならないインメモリDBのいずれかの重要な設定が足りませんか?違いは奇妙に見えますが、正直なところ、非常に混乱しています。

すべてのコードは、.NETのコア2.0をターゲットにしています。

<PropertyGroup> 
    <OutputType>Exe</OutputType> 
    <TargetFramework>netcoreapp2.0</TargetFramework> 
</PropertyGroup> 

<ItemGroup> 
    <PackageReference Include="System.ComponentModel.Annotations" Version="4.4.0" /> 
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.0.0" /> 
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.0.0" /> 
    <PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="2.0.0" /> 
    <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="2.0.0" /> 
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.0.0" /> 
</ItemGroup> 

大歓迎任意のヘルプ。

+0

流暢なAPIを使って並行性トークンを設定しようとしましたか? –

+0

はい、私は: modelBuilder.Entity () \t \t .Property(P => p.RowVersion) \t \t .ValueGeneratedOnAddOrUpdate() \t \t .IsConcurrencyToken() \t \t。 –

+0

OK、前のコードは、おそらく右ではなかったが、この1つはどちらも動作しません:modelBuilder.Entity () \t \t .Propertyた(p => p.RowVersion)を \t \t .ValueGeneratedOnAddOrUpdate() .IsRowVersion () ; –

答えて

2

InMemoryでテストしたdocsは、期待管理を重視しています。たとえば、

(InMemory)は、リレーショナルデータベースを模倣するようには設計されていません。とりわけ、インメモリは、リレーショナルデータベースの参照整合性制約に違反するデータを保存することができます

  • を意味し、

  • あなたは、モデル内のプロパティのDefaultValueSql(文字列)を使用している場合、これはリレーショナルデータベースAPIで、インメモリに対して実行したときには効果がありません。初期化とRowVersion列値を更新

  • 間違いなく、このリストに追加することができます。

    それから、彼らはヒントを与える:多くのテスト目的のために

    これらの違いは問題ではありません。しかし、真のリレーショナルデータベースのように動作するものに対してテストする場合は、SQLiteのメモリ内モードを使用することを検討してください。

    私は価値があることについて、最初の部分に同意します。違いは分かっていないものをテストします。 InMemoryは、ビジネスロジックユニットのテストで後で使用するモックデータのクイックサプライヤとしてだけデータベースレイヤを使用する場合に便利です。

    しかし、正しいデータレイヤーの動作により依存する関数をテストするためにSQLiteを使用するという2番目のアドバイスには心から反対しています。さて、SQLiteが運用データベースの場合は、先に進んでください。それ以外の場合は、本番データベースと同じデータベース・ブランドに対して常に統合テストを行います。統合テストを十分に信頼できるものにするために、データベースブランドとクエリプロバイダ(式をSQLに変換する部分)には多すぎる違いがあります。また、SQLiteが独自のデータベースブランド/クエリプロバイダが行うLINQの構文や文や機能をサポートしていない場合はどうなりますか? SQLiteを気に入らないようにしますか?私はそうは思わない。

    私のアドバイスは、RowVersion関連のコードをテストするためのSQL Server統合テストデータベースをセットアップすることです。

    +0

    偉大な答え、ありがとう。 InMemoryが他のRDBMSとして動作することを期待していたため、私の前提が間違っていた可能性があります。違いがより根本的であるように見えます。実装された機能や欠落している機能のリストがないことは本当に役に立ちますが、私は何かを見つけるのは不運でした。 SQLiteの方がはるかに優れています。https://docs.microsoft.com/en-us/ef/core/providers/sqlite/limitations これは統合テストと見なすことができるというあなたの意見を見ることができます。私の観点からは(私はよりDB指向です)、タイムスタンプが正しく維持されていないのはバグであり、機能ではありません。 –

    +0

    私はEFチームがあなたの意見を共有しているとは思わない。バグとは、主張されているように実行されないものです*(期待通り*ではありません)。 RowVersionsがInMemoryでサポートされることは決してないと私は確信しています。 (誰にも言わないでくださいが、InMemoryの実用的な使用方法はあまり見当たりません。私のDALが自動化されたテストのどこにあっても、本当のことを100%確実にしたいからです。時間がかかる、私はスピードよりも正確さを好む)。 –

    関連する問題