2012-04-26 54 views
0

在試圖減少代碼和班級我用我一直在考慮這個方法量:通用實體保存方法不起作用?

public TEntity Save(TEntity entity) 
      { 
       var validatationErrors = Entities.GetValidationErrors().ToList(); 
       if (validatationErrors.Count() > 0) 
        throw new ValidateException(validatationErrors); 

       if (Entities.Entry(entity).State == EntityState.Added) 
        Entities.Set<TEntity>().Add(entity); 
       else 
        Entities.Set<TEntity>().Attach(entity); 

       Entities.SaveChanges(); 
       Entities.Entry(entity).Reload(); 
       return entity; 
      } 

當我創建一個新的產品但它跳過了條件,將它添加到數據庫中。因此沒有得到保存。同樣,如果我嘗試修改它不會更改的內容。

爲了解決這個問題我要救我的實體在控制器中,像這樣:

using (var db = new EntitiesDbContext()) 
       { 
        db.Products.Attach(product); 
        db.Entry(product).State = EntityState.Modified; 
        db.SaveChanges(); 
       } 

這似乎是相當低效。 所以我想知道真的是什麼問題的通用保存,使其無法正常工作?

+0

你有設置狀態來添加/修改?也就是說,Entities.Entry(entity).State' =='EntityState.Added'或'EntityState.Modified'? – 2012-04-27 05:43:53

+0

我在哪裏設置?我目前正從控制器操作中設置它,但這看起來效率很低。 – Johannes 2012-04-27 14:08:02

回答

0

如果你創建一個新的實體,你應該使用.Add方法。 。如果你有一個你知道它存在於數據庫中的對象,並且你想避免訪問數據庫來獲取它,應該使用附件。

而且一般的保存方法似乎有幾個問題:

  • 除非您禁用驗證明確你會不止一次驗證實體,因爲在默認情況下.SaveChanges()如果實體將驗證實體
  • 處於Added狀態,它已被上下文跟蹤,因此不需要再次添加它
  • .SaveChanges()將嘗試保存上下文跟蹤的所有實體不處於未更改狀態。該方法使一個印象是,它只會保存您通過實體,但實際上它可能保存超過該
  • 我想調用DbEntityEntry.Reload()纔有用連接實體從數據庫值更新屬性值 - 如果你總是這樣做,那麼我想知道你爲什麼附加實體而不是從數據庫中獲取它。
+0

沒錯。所以有一個.Add方法,但是EntityState.Added條件被跳過。該方法不保存額外的東西,它不會保存任何東西。理想情況下,儘管保存方法應該能夠處理創建和更新。但我同意設計有問題。我只是不知道如何讓它創建新的實體和更新編輯的實體。 – Johannes 2012-04-27 15:04:38

+0

如果您有一個新的實體只使用Enities.Set ().Add()。如果您修改了實體屬性並且跟蹤了實體(即您首先從數據庫中獲取了它),則無需執行任何操作。 EF會發現它已被修改,並且在調用.SaveChanges()時應該將更改(以及新實體)保存到數據庫中。老實說,我不確定我會使用通用方法。 – Pawel 2012-04-27 16:31:41

+0

所以你認爲爲每個實體創建一個保存方法將是更明智的做法? – Johannes 2012-04-27 16:36:33

1
  • 你的代碼是錯誤的。在你的情況下,你不需要Attach你的實體。你只需要你的實體AddDbSet

     public TEntity Save(TEntity entity) 
         { 
          Entities.Set<TEntity>().Add(entity);   
          Entities.SaveChanges(); 
         } 
    

你應該記住:

Entities.Set<TEntity>().Add(entity);

等於

db.Entry(entity).State = EntityState.Added;

entity.Property = newProperty;

集實體狀態Modifieddb.Entry(entity).StateEntityState.Modified

而且你也不需要驗證和重新加載實體。 ObjectContext爲你做。

  • 中來控制你的實體嘗試這個辦法:

    public TEntity Save(TEntity entity) 
        { 
    
         var dbEntity = Entities.Set<TEntity>().Find(entity.Id); 
    
         if (dbEntity != null)    
          dbEntity = entity; 
         else 
          Entities.Set<TEntity>().Add(entity); 
    
         Entities.SaveChanges(); 
        } 
    
+0

10我如何正確地調整添加?因爲沒有條件,當你編輯它時你會添加一個新的實體實例。 – Johannes 2012-04-27 15:21:00

+0

將代碼添加到我的答案 – algreat 2012-04-27 15:34:18

+0

好吧,但由於它是通用的,因此您不能從實體中提取標識,因爲您實際上並不知道它是哪個實體。並拉動整個實體'Entities.Set ().Find(entity);'是不允許的。 – Johannes 2012-04-27 15:35:26