Asp.net Core DBContextのXUnitテストを実装しようとしましたが、エラーが発生しました。EFコアアップデートエンティティタイプ 'Ads'のインスタンスはトラッキングできません
メッセージ:System.InvalidOperationException:エンティティタイプ 'Ads'のインスタンスは、同じキーを持つこのタイプの別のインスタンスが既にトラッキングされているため、トラッキングできません。新しいエンティティを追加する場合、ほとんどのキータイプでは、キーが設定されていない場合(キープロパティにそのタイプのデフォルト値が割り当てられている場合)、一意の一時キー値が作成されます。新しいエンティティのキー値を明示的に設定する場合は、既存のエンティティや他の新しいエンティティ用に生成された一時的な値と衝突しないようにしてください。既存のエンティティをアタッチする場合は、指定されたキー値を持つエンティティインスタンスが1つだけコンテキストにアタッチされていることを確認します。
は、ここに私の現在のコードです:
public class AdsServiceTest
{
private readonly DbContextOptions<SensingSiteDbContext> _options;
private readonly SensingSiteDbContext _context;
private readonly AdsService _AdsService;
public AdsServiceTest()
{
//initialize db options
_options = new DbContextOptionsBuilder<SensingSiteDbContext>()
.UseInMemoryDatabase()
.Options;
//get service
_context = new SensingSiteDbContext(_options);
//initialize dbcontext
List<Ads> listAds = new List<Ads>() {
new Ads(){ Id=1,AdsName="Ads1", Deleted=false},
new Ads(){ Id=2,AdsName="Ads1", Deleted=false},
new Ads(){ Id=3,AdsName="Ads1", Deleted=false}
};
_context.Advertisements.AddRange(listAds);
//context.Advertisements
BaseLib.SSDbContext<Ads, AdsService> ssDbContent = new BaseLib.SSDbContext<Ads, AdsService>(_context);
_AdsService = ssDbContent.GetService((x, y) => new AdsService(x, y));
}
[Theory]
[InlineData(1)]
public void FindById(int id)
{
Ads adsResult = _AdsService.FindById(id);
Ads adsTarget = _context.Advertisements.Find(adsResult.Id);
Assert.True(adsTarget.Equals(adsResult));
}
//Failed by error System.InvalidOperationException : The instance of entity type 'Ads' cannot be tracked because another instance of this type with the same key is already being tracked
[Fact]
public void Update()
{
Ads adsResult = new Ads() { Id = 1, AdsName = "UpdateAds1" };
_AdsService.UpdateAds(adsResult);
Ads adsTarget = _context.Advertisements.Find(adsResult.Id);
Assert.True(adsTarget.Equals(adsResult));
}
}
検索には問題ありませんが、更新に失敗しました。 AdsServiceは、SensingSiteDbContextを呼び出すように実装されています。私はSensingSiteDbContextのスコープライフタイムを使用する必要があるようです。しかし、私はそれを実装する方法を知らない。
私はObjectState for Updateを変更しました。
public virtual void Update(TEntity entity)
{
entity.ObjectState = ObjectState.Modified;
_dbSet.Update(entity);
_context.SyncObjectState(entity);
}
助けてください。
意味しますか;'?私の選択では、 'entity.ObjectState = ObjectState.Modified'を使うと、新しいオブジェクトを受け入れることができます。そうでなければ、私は提出書類を一つずつセットする必要があります。 –
問題は '_dbSet.Update(エンティティ)'呼び出しにはなく、コンテキストでどのオブジェクトを使用しているかにあります。更新テストで使用している 'new Ads()'をコンテキストから取得するか、あなたがやっていることを実行して、 'Context.Attach(entity)'を最初に呼び出すことができます。外部から渡すオブジェクトを調整します。 – steamrolla