2017-08-28 31 views
0

我正在開發一個控制檯應用程序,該應用程序將執行由一組複雜業務組成的單個事務邏輯。在此事務中會調用多個服務,並且幾乎可以肯定的是,任何給定的實體都將在存儲庫中多次更新。在一長串計算中,我該如何避免「實體類型'Person'的實例無法跟蹤......」

我正在使用依賴注入來注入我的存儲庫,服務,dbcontext和工作單元,無論他們需要什麼。在很早的階段,交易看起來是這樣的:

using (var scope = serviceProvider.CreateScope()) 
{ 
    var dbContext = scope.ServiceProvider 
     .GetRequiredService<FantasySimulationDBContext>(); 

    using (var dbContextTransaction = 
     dbContext.Database.BeginTransaction()) 
    { 
     try 
     { 
      var flowControllerService = 
       scope.ServiceProvider.GetService<IFlowControllerService>(); 
      flowControllerService.IncrementTime(); 
      flowControllerService.IncrementTime(); 
      dbContextTransaction.Commit(); 
     } 
     catch (Exception e) 
     { 
      dbContextTransaction.Rollback(); 
     } 
    } 
} 

我只能叫flowControllerService.IncrementTime()兩次來說明我想擁有的功能類型。我希望這是一種可能性,現在不是。

在我服務的IncrementTime方法是這樣的:

public void IncrementTime() 
    { 

     //do a bunch of stuff to a "Person" object 
     _personRepository.UpdatePerson(person); 
     _unitOfWork.Complete(); 
    } 

的PersonRepository映射我的域模型回持久性模型,並在更新的DbContext他們。它看起來像這樣:

public class PersonRepository: IPersonRepository 
{ 
    private readonly FantasySimulationDBContext _dbContext; 
    private IMapper _mapper; 

    public PersonRepository(FantasySimulationDBContext context, IMapper mapper) 
    { 
     _dbContext = context; 
     _mapper = mapper; 
    } 
    ... 
    public void UpdatePerson(Person person) 
    { 
     var mappedPerson = _mapper.Map<PersistenceModels.Person>(person); 
     _dbContext.People.Update(mappedPerson); 
    } 
} 

什麼最終發生的是第一次調用IncrementTime工作正常。但是,第二次調用會導致發生以下異常:「實體類型'Person'的實例無法跟蹤,因爲具有相同鍵的此類型的另一個實例已被跟蹤。」我知道這是因爲當我第一次保存時,我保存的「Person」仍然在dbContext的changetracker中,然後在第二次調用IncrementTime時重新使用相同的dbContext。因此,當人員儲存庫嘗試第二次更新同一個人時,我會收到異常,因爲它已經在更改跟蹤器中。

我可以在每次提交工作單元后分離所有內容,但是我從來沒有在其他人的代碼中看到過,所以我假設我的整個過程的某些基本方面是錯誤的。那麼處理這個問題的正確方法是什麼呢?或者說,我在設計這個方面有什麼失誤?

回答

0

基本上有兩種方法可以做到這一點從我可以告訴(除了你說的方式:分離等)。首先,您可以堅持實體並更新它,而不是您正在使用的「DTO」。其他將是獲取Person這樣的實例:

var personModel = _dbContext.People.Find(person.ID); 
_mapper.Map(person, personModel); 
_dbContext.SaveChanges(); 

你總是隻使用單一實例的方式,你DBContext已經緊緊抓住和跟蹤。

+0

我一直在嘗試你列出的第二種方法,但據我所知,它標記任何對象的嵌套集合中的人作爲「添加」的變化跟蹤器,它會導致各種問題,當它嘗試保存。我嘗試使用AutoMapper.Collection來解決這個問題,但我無法讓它在dot net core中工作。 – LayfieldK

相關問題