具有存储库模式的MVC脚手架 - 将子对象保存为事务

时间:2021-01-18 02:13:36

I have been scouring forums and repository pattern blogs for some clear direction on how I should be coding my project and I'm stuck. Any help or guidance from you guys would be much approciated :)

我一直在搜索论坛和存储库模式博客,以便对我应该如何编写项目进行一些明确的指导而且我被卡住了。你们的任何帮助或指导都会得到很多帮助:)

I started my project as EF5 MVC4 Razor Code First and decided to use MVCScaffolding to generate all my controllers, views and repositories. This was my first project with these technologies, I was just told that this was how the team was doing it now (but the previous developers did model first and hand coded their contexts).

我以EF5 MVC4 Razor Code First开始我的项目,并决定使用MVCScaffolding生成我的所有控制器,视图和存储库。这是我第一个使用这些技术的项目,我刚刚被告知这就是团队现在正在做的事情(但之前的开发人员先做过模型并手工编写了他们的上下文)。

SO, all is great, we're coding a bunch of screens, but one of our screens is a complex one that involves many models/sub modlels (ie/ Object model has FKs to Responses, Attachments, Reviewers, etc...). The user adds a bunch of data, selects one or more reviewers, adds 0 or more attachments. Then they hit Save!

所以,一切都很好,我们正在编写一堆屏幕,但我们的一个屏幕是一个复杂的屏幕,涉及许多模型/子模块(即/对象模型有FK到响应,附件,审阅者等...) 。用户添加一堆数据,选择一个或多个审阅者,添加0个或更多附件。然后他们点击Save!

Now my big problem is that I want to save all this data as one transaction, and if something fails on one of the children models (ie/ attachments) the transaction will roll back. However, the way the MVCScaffolding repositories are created, each model has it's own instance of DB Context and it's own Save. And the controllers accept each unique repository as parameters for loading the screen data. Another thing to note is for this screen we are using a ViewModel to load the data, and then wrote custom mappers to map back to the different models for saving. We can save each piece separately, and possibly the solution is just to wrap TransactionScope around my save, but I also want to reduce the number of calls to the db, as each repository save does a call.

现在我的大问题是我想将所有这些数据保存为一个事务,如果其中一个子模型(即/附件)出现故障,事务将回滚。但是,创建MVCScaffolding存储库的方式,每个模型都有自己的DB Context实例,并且它自己的Save。控制器接受每个唯一的存储库作为加载屏幕数据的参数。另外需要注意的是,对于这个屏幕,我们使用ViewModel来加载数据,然后编写自定义映射器以映射回不同的模型以进行保存。我们可以单独保存每个部分,可能解决方案只是围绕我的保存包装TransactionScope,但我也想减少对db的调用次数,因为每个存储库保存都会进行调用。

I thought I could add code to the parent repository for a UnitsOfWork type save that would add/edit all the child obejcts in one context object, but that seems like a hack more than anything, and I want to code this properly.

我以为我可以将代码添加到父存储库中以获取可以在一个上下文对象中添加/编辑所有子对象的单元,但这似乎比任何东西都更糟糕,我想要正确编码。

One of the other projects here just made a custom DB context and all Save methods were in that class, is that the best way to do it? Another dev did code first but hand coded all his Save methods. None of them are in a standard place and he is using TransactionScope with a DBContext inside (is that overkill or does DBContext not handle transactions)?

这里的其中一个项目只是创建了一个自定义的DB上下文,并且所有Save方法都在该类中,这是最好的方法吗?另一个开发人员首先编码,但手工编码所有他的Save方法。他们都没有在标准的地方,他正在使用TransactionScope与DBContext里面(是过度杀戮还是DBContext没有处理交易)?

Since I'm so new to this, I need help and no one I work with seems to agree on a proper method. I'm not sure if my model is wrong for an "MVC App" since I'm such a database heavy thinker.

由于我对此很陌生,我需要帮助,与我合作的任何人似乎都不同意正确的方法。我不确定我的模型是否对于“MVC应用程序”是错误的,因为我是一个数据库沉重的思想家。

Below is a sample of my models, any guidance is appreciated. Thanks :)

以下是我的模型样本,任何指导表示赞赏。谢谢 :)

public class Anomaly 
{
    [Key]
    public int AnomalyId { get; set; }

    public string Subject { get; set; }

    public int PlantId { get; set; }
    [ForeignKey("PlantId")]
    public virtual Plant Plant { get; set; }

    public DateTime? ReviewByDate { get; set; }

    public virtual ICollection<AnomalyReviewer> AnomolyReviewers { get; set; }
    public virtual ICollection<AnomalyAttachment> AnomalyAttachments { get; set; }

}

    public class AnomalyAttachment 
{
    [Key]
    public int AnomalyAttachmentId { get; set; }

    public int AnomalyId { get; set; }
    [ForeignKey("AnomalyId")]
    public virtual Anomaly Anomaly { get; set; }

    public string FilePath { get; set; }
    public string FileName { get; set; }
    public string FileExtension { get; set; }
    public string Notes { get; set; }           

}

ps. that is just a sample... thanks!

PS。这只是一个样本...谢谢!

1 个解决方案

#1


1  

Just create a class 'Master' that inherits from Controller. Then write all your queries there as in public User GetUserById(Int32 id) Finally create a function that does a call to the private!! implementation of DbContext.

只需创建一个继承自Controller的类“Master”。然后在公共用户GetUserById(Int32 id)中写下你所有的查询。最后创建一个调用私有的函数!! DbContext的实现。

I would usually give that function a enum of SystemEvents so i've got a reference of whats happening if something would fail... of course you would need to write your own notificator or model to record your own errors into the database for personal testing...

我通常会给这个函数一个SystemEvents的枚举,所以我有一个参考,如果有什么东西会失败的话会发生什么......当然你需要编写自己的通知器或模型来将你自己的错误记录到数据库中进行个人测试...

ive done all this because I can write all my code and found out that Repository Pattern is overkill most of the time if you actually think about it.

我已经完成了所有这些,因为我可以编写所有代码,并发现如果你真的想到它,Repository Pattern在大多数情况下都是过度的。

#1


1  

Just create a class 'Master' that inherits from Controller. Then write all your queries there as in public User GetUserById(Int32 id) Finally create a function that does a call to the private!! implementation of DbContext.

只需创建一个继承自Controller的类“Master”。然后在公共用户GetUserById(Int32 id)中写下你所有的查询。最后创建一个调用私有的函数!! DbContext的实现。

I would usually give that function a enum of SystemEvents so i've got a reference of whats happening if something would fail... of course you would need to write your own notificator or model to record your own errors into the database for personal testing...

我通常会给这个函数一个SystemEvents的枚举,所以我有一个参考,如果有什么东西会失败的话会发生什么......当然你需要编写自己的通知器或模型来将你自己的错误记录到数据库中进行个人测试...

ive done all this because I can write all my code and found out that Repository Pattern is overkill most of the time if you actually think about it.

我已经完成了所有这些,因为我可以编写所有代码,并发现如果你真的想到它,Repository Pattern在大多数情况下都是过度的。