2017-07-28 95 views
0

我試圖創建一個使用EF的Web API程序。現在,我的控制器中有一些CRUD函數,它們用於創建新對象,刪除對象和讀取對象。當我嘗試更新數據庫中存在的一個對象時,問題就出現了,接收到標題中的錯誤。我已經嘗試了一些也有這個問題的人的解決方案,並在這裏問了一個問題,但現在沒有任何工作。實體框架:連接類型爲FixedAssets的實體失敗,因爲另一個相同類型的實體已具有相同的主鍵值

這裏是我的代碼:

從我的控制器的方法:

[HttpPost] 
    [Route("UpdateAsset")] 
    public HttpResponseMessage UpdateAsset(HttpRequestMessage request, FixedAssetsView assets) 
    { 
     return CreateHttpResponse(request,() => 
     { 
      HttpResponseMessage response = null; 

      if (!ModelState.IsValid) 
      { 
       response = request.CreateResponse(HttpStatusCode.BadRequest, 
        ModelState.Keys.SelectMany(k => ModelState[k].Errors) 
          .Select(m => m.ErrorMessage).ToArray()); 
      } 
      else if (!service.isInDatabase(assets.ID)) 
      { 
       ModelState.AddModelError("Error", "Couldn't find the assets you want to update"); 
       response = request.CreateResponse(HttpStatusCode.BadRequest, 
       ModelState.Keys.SelectMany(k => ModelState[k].Errors) 
         .Select(m => m.ErrorMessage).ToArray()); 
      } 
      else if (service.isInDatabaseAfterInventoryNo(assets.inventoryNo) && service.getAssetIdAfterInventoryNumber(assets.inventoryNo) != assets.ID) 
      { 
       ModelState.AddModelError("Invalid object", "An assets with the same inventory number already exists"); 
       response = request.CreateResponse(HttpStatusCode.BadRequest, 
       ModelState.Keys.SelectMany(k => ModelState[k].Errors) 
         .Select(m => m.ErrorMessage).ToArray()); 
      } 
      else 
      { 
       if (service.wasUpdated(assets)) 
        response = request.CreateResponse(HttpStatusCode.OK, "Success"); 
       else 
        response = request.CreateResponse(HttpStatusCode.InternalServerError); 
      } 

      return response; 
     }); 
    } 

我從服務中使用的方法:

public bool isInDatabase(int ID) 
    { 
     return assetsRepo.FindBy(asset => asset.ID == ID).Any(); 
    } 

    public bool isInDatabaseAfterInventoryNo(int inventoryNo) 
    { 
     return assetsRepo.FindBy(asset => asset.inventoryNo == inventoryNo).Any(); 
    } 

    public int getAssetIdAfterInventoryNumber(int inventoryNo) 
    { 
     return assetsRepo.FindBy(asset => asset.inventoryNo == inventoryNo).First().ID; 
    } 

    public bool wasUpdated(FixedAssetsView assets) 
    { 
     FixedAssets singleAsset = Mapper.Map<FixedAssetsView, FixedAssets>(assets); 
     assetsRepo.Edit(singleAsset); 
     unitOfWork.Commit(); 
     return true; 
    } 

我從我的倉庫使用的方法:

public virtual IQueryable<T> FindBy(Expression<Func<T, bool>> predicate) 
    { 
     return DbContext.Set<T>().Where(predicate); 
    } 

    public virtual void Edit(T entity) 
    { 
     DbEntityEntry dbEntityEntry = DbContext.Entry<T>(entity); 
     dbEntityEntry.State = EntityState.Modified; /*HERE IS WHERE RECEIVE THE EXCEPTION*/ 
    } 

這裏是我的DbContext方法:

private InventoryManagementContext dataContext; 

    protected InventoryManagementContext DbContext 
    { 
     get { return dataContext ?? (dataContext = DbFactory.Init()); } 
    } 

我DbFactory方法:

protected IDbFactory DbFactory 
    { 
     get; 
     private set; 
    } 

我IDbFactory接口:

public interface IDbFactory : IDisposable 
{ 
    InventoryManagementContext Init(); 
} 

我InventoryManagementContext:

public class InventoryManagementContext : DbContext 
{ 
    // You can add custom code to this file. Changes will not be overwritten. 
    // 
    // If you want Entity Framework to drop and regenerate your database 
    // automatically whenever you change your model schema, please use data migrations. 
    // For more information refer to the documentation: 
    // http://msdn.microsoft.com/en-us/data/jj591621.aspx 

    public InventoryManagementContext() : base("name=InventoryManagementContext") 
    { 
     Database.SetInitializer<InventoryManagementContext>(null); 
    } 

    public System.Data.Entity.DbSet<InventoryManagement.Models.InventoryObjects> InventoryObjects { get; set; } 

    public System.Data.Entity.DbSet<InventoryManagement.Models.FixedAssets> FixedAssets { get; set; } 

    public virtual void Commit() 
    { 
     base.SaveChanges(); 
    } 
    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); 

     modelBuilder.Configurations.Add(new FixedAssetsConfiguration()); 
     modelBuilder.Configurations.Add(new InventoryObjectsConfiguration()); 
    } 
} 

感謝您HEL頁。

+0

你有沒有在固定資產中設置PK?它的價值是什麼?你如何管理你的回購/ UoW的生命週期? – Fermin

+0

我的FixedAssets擁有您可以在我的代碼中找到的ID。我不太瞭解生命週期問題:/ – Artyomska

+0

「生命週期」意味着您是爲每個請求創建上下文還是創建一次並在應用程序的整個生命週期中使用它? – Fermin

回答

0

我修復了這個問題。對於未來的用戶,我更新了FindBy函數

public virtual IQueryable<T> FindBy(Expression<Func<T, bool>> predicate) 
{ 
    return DbContext.Set<T>().Where(predicate).AsNoTracking(); 
} 

注意「AsNoTracking()」的加法。

相關問題