2017-07-28 4 views
0

EFを使用するWeb APIプログラムを作成しようとしています。今、私は新しいオブジェクトの作成、オブジェクトの削除、オブジェクトの読み込みのために働いている私のコントローラにいくつかのCRUD関数を持っています。この問題は、データベースに存在するオブジェクトを更新しようとしたときに、タイトルからエラーが発生したときに発生します。私はすでにこの問題を抱えていた人々からいくつかの解決策を試してみましたが、ここで質問しましたが、今は何も働いていません。ここでEntity Framework:同じタイプの別のエンティティがすでに同じプライマリキー値を持っているため、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()); 
    } 
} 

をいただきありがとうございますあなたヘイp。

+0

FixedAssetsでPKをセットアップしましたか?その価値は何ですか?あなたのレポ/ウーのライフサイクルをどのように管理していますか? – Fermin

+0

私のFixedAssetsはあなたのコードで見つけることができるPKのIDを持っています。私は実際にライフサイクルの質問を理解していません:/ – Artyomska

+0

"ライフサイクル"とは、各リクエストのコンテキストを作成するか、一度作成してアプリケーションのライフタイム全体で使用することですか? – Fermin

答えて

0

問題を修正しました。将来それを持つ人のために、私はFindBy関数を更新しました。

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

"AsNoTracking()"の追加に注目してください。

関連する問題