2012-04-26 48 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