扩展模型对象(例如 Product)并添加插入数据库的 Create() 方法是否正确? (MVC 5 Entity Framework 6)

Is it proper form to extend a model object (e.g. Product) and add a Create() method that inserts into the database? (MVC 5 Entity Framework 6)

所以我目前正在扩展 Entity Framework 为我的数据库中的每个表自动生成的 classes。我在这些进行扩展的部分 classes 中放置了一些有用的方法来处理数据。

但是,我的问题是关于在数据库中插入行。在我的扩展 classes 中包含一个方法来处理这个问题会是一种好的形式吗?

例如,在 Product 控制器的 Create 方法中有这样的内容:

[HttpPost]
public ActionResult Create(Product p)
{
    p.InsertThisProductIntoTheDatabase();  //my custom method for inserting into db
    return View();
}

我觉得这件事有些不对劲,但我也说不准。感觉这个功能应该放在通用的 MyHelpers.cs class 或其他东西中,然后就这样做:

var h = new MyHelpers();
h.InsertThisProductIntoTheDatabase(p);

大家怎么看?我更愿意以 "correct" 的方式进行。


MVC 5、EF 6


编辑:InsertThisProductIntoTheDatabase 方法可能类似于:

public partial class Product()
{

    public void InsertThisProductIntoTheDatabase()
    {
         var context = MyEntities();

         this.CreatedDate = DateTime.Now;
         this.CreatedByID = SomeUserClass.ID;
         //some additional transformation/preparation of the object's data would be done here too.  My goal is to bring all of this out of the controller.

         context.Products.Add(this);
    }

}

你为什么不简单地使用:

db.Products.Add(p);
db.SaveChanges();

您的代码会更简洁,而且您将来管理它并获得帮助肯定会更容易。互联网上可用的大多数示例都使用此模式。扩展方法和实体看起来不愉快。

顺便说一句:InsertThisProductIntoTheDatabase() 方法名是不是太长了?

我看到的一个问题是 entity framework DBContext 是一个工作单元。如果在将 Application_BeginRequest 传递给控制器​​构造函数时在 Application_BeginRequest 上创建了一个工作单元,那么它将作为整个请求的一个工作单元。也许它只更新了您场景中的 1 个实体,但您可能正在将更多信息写入数据库。除非您将所有内容都包装在 TransactionScope 中,否则所有这些保存都将是独立的,这可能会使您的数据库处于不一致的状态。即使您用 TransactionScope 包装所有内容,我也很确定事务将被提升到 DTC,因为您在单个控制器中建立多个物理连接并且 sql 服务器不是那么智能。

走 BeginRequest 路线似乎比向所有实体添加方法以保存自身更省力。这里的另一个问题是 EF 实体应该是一个对它自己的持久性一无所知的实体。这就是 DbContext 的用途。因此,将引用放回 DbContext 会打破这种隔离。

你的第二个原因,将审计信息添加到实体,再次将其添加到每个实体需要大量工作。您可以覆盖上下文中的 SaveChanges 并为每个实体执行一次。看到这个 answer.

沿着这条路走下去,我认为您违反了 SOLID 设计原则,因为您的实体违反了 SRP。引入一堆内聚,你最终会编写比你需要的更多的代码。所以我反对按照你的方式去做。