Cerco di implementare un test XUnit per Asp.net Core DBContext, ma ho ottenuto l'errore di sotto.
Messaggio: System.InvalidOperationException: l'istanza del tipo di entità "Annunci" non può essere tracciata perché un'altra traccia di questo tipo con la stessa chiave è già stata tracciata. Quando si aggiungono nuove entità, per la maggior parte dei tipi di chiave verrà creato un valore di chiave temporanea univoco se non viene impostata alcuna chiave (cioè se alla proprietà della chiave viene assegnato il valore predefinito per il suo tipo). Se si impostano in modo esplicito valori chiave per le nuove entità, assicurarsi che non entrino in collisione con entità esistenti o valori temporanei generati per altre nuove entità. Quando si allegano entità esistenti, assicurarsi che solo una istanza di entità con un dato valore chiave sia allegata al contesto.
Ecco il mio codice attuale:
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));
}
}
Non c'è alcun problema per Trova, ma non è riuscito su Aggiornamento. AdsService è implementato per chiamare SensingSiteDbContext. Sembra che ho bisogno di utilizzare la durata dell'ambito per SensingSiteDbContext. Ma, non so come implementarlo.
Ho cambiato ObjectState per l'aggiornamento.
public virtual void Update(TEntity entity)
{
entity.ObjectState = ObjectState.Modified;
_dbSet.Update(entity);
_context.SyncObjectState(entity);
}
Qualsiasi aiuto sarebbe apprezzato.
Sei new
nel creare la tua entità, quando, dovresti semplicemente avere quell'entità che hai già aggiunto dal contesto:
Ads adsResult = new Ads() { Id = 1, AdsName = "UpdateAds1" };
_AdsService.UpdateAds(adsResult);
Con questo codice, Entity Framework sta dicendo: "Ehi, ho già un'entità con quella chiave (controlla il tuo costruttore, stai mettendo un'entità con lo stesso Id), ma questo oggetto, non so cosa fare con esso (perché è venuto dall'esterno con una chiave che esiste già) ".
Puoi cambiare esattamente ciò che stai facendo nel test precedente:
Ads adsResult = _AdsService.FindById(id);
//do your changing here
_AdsService.UpdateAds(adsResult);