Entity First MVC3 站点的优雅验证技术?

发布于 2024-12-10 09:28:42 字数 507 浏览 1 评论 0原文

由于从未做过 MVC 站点,我即将开始一个非常大的项目。我有足够的信心去做这件事,但我有件事需要帮助解决。

我们肯定会使用“实体优先”方法并使用单个 .edmx 文件定义模型,造成这种情况的原因有多种,但只要知道这是难题的一个明确部分即可。

因此,我需要弄清楚的是,如何提出一种优雅的方法来对页面上的实体进行验证,而无需对每个页面进行手动编码,至少对于大多数事情来说是这样。

是否有一些已经流行的方法来进行一些基本验证?像 MaxLength、Required 或 MinDate 之类的东西?

任何比这更复杂的事情,我知道我必须自己编写代码,但是这个网站将会非常大,我真的需要找到一种方法来加快一些基本任务的速度。

编辑
我应该指出几个重要的事实。
1) 我们的数据库已经存在,并且是在开发人员介入之前由 DBA 创建的。
2) 已经创建了数百个表和存储过程。
3) 当需要对数据库进行更改时,它们将通过 DBA,而我们并不总是能够立即访问 DBA。

Having never done an MVC site I am about to start a project for a very large one. I feel confidant enough to do it, but I have one thing I need help figuring out.

We are definitely going to be using an "Entity First" method and have a single .edmx file defining the models, there are multiple reasons for this but just know that this is a definite piece of the puzzle.

So the piece I need to figure out is how to come up with an elegant way to do validations against Entities on a page, without hand coding each page, at least for the majority of things.

Are there any already popular methods for doing some basic validations? Things like MaxLength or Required or MinDate, etc?

Anything more complex than that and I understand I'd have to code it myself, but this site is going to be very large and I really need to find a way to speed some of the basic tasks up.

EDIT
I should point out a couple important facts.
1) Our database already exists and was created by a DBA before developers even came into the picture.
2) There are hundreds of tables and stored procedures already created.
3) When changes will need to be made to the database, they will go through the DBA, who we will not always have instant access too.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

糖果控 2024-12-17 09:28:42

首先,如果您使用 Entity Framework Code First,则没有 .edxm 文件来存储模型或它们之间的关系:您只需编写 POCO(普通旧 CLR 对象)类,仅此而已 - Code First 会计算根据命名约定找出模型之间的关系。


要验证您的(视图)模型,我建议使用 FluentValidationDataAnnotations。两者都允许您在一处定义验证规则,可以在不同的实体验证类 (FluentValidation) 中使用流畅的验证 API,或者使用属性来装饰实体属性 (DataAnnotations)。 DataAnnotations 相对于 FluentValidation 的优势在于您可以立即获得额外的客户端验证。

无论您选择哪个框架,两者都附带了一堆预定义的验证规则,例如 RequiredRangeMaxLength(请参阅 .NET 的 Fluent 验证System.ComponentModel.DataAnnotations 命名空间 作为示例)。

First of all, if you use Entity Framework Code First, you don't have a .edxm file storing your models or relationships between them: you just write your POCO (Plain Old CLR Object) classes, and that's it — Code First will figure out the relations between your models based on naming conventions.


To validate your (view) models, I recommend using FluentValidation or DataAnnotations. Both let you define validation rules in one place, either using a fluent validation API in different entity validation classes (FluentValidation) or using attributes to decorate your entity properties (DataAnnotations). The advantage of DataAnnotations over FluentValidation is that you get additional client-side validation out of the box.

Whichever framework you choose, both ship with a bunch of predefined validation rules like Required, Range, or MaxLength (see Fluent Validation for .NET or System.ComponentModel.DataAnnotations Namespace for examples).

行至春深 2024-12-17 09:28:42

我绝对会 100% 仍然使用一些 POCO 类。下载 DBContext 生成器模板,该模板随后将首先从您的模型创建代码,或者使用 Entity Framework Power Tools 对现有数据库进行逆向工程。但这些方法的缺点是您不会获得客户端验证,只有在保存时才会获得验证。但是,如果您除了使用之外还选择进行客户端验证,您仍然可以添加验证属性
元数据类,用于在属性上使用数据注释并使用以下方式进行客户端验证内置 jQuery 不显眼的验证。

然而,我们在这里讨论的内容无论如何都违背了 MVC 良好实践的基本设计。理想情况下,您的视图应该具有有时只是实体的一部分的 ViewModel,在这种情况下,您的验证属性仍然在您的属性上生成为 MetaDataClasses 中的 DataAnnotations。

如果您觉得这工作量太大,并且您只需进行服务器验证即可,并决定不使用 ViewModel 并依赖实体框架验证,或者使用 ViewModel 并仍然依赖 EF 验证,那么您将需要控制器(或已被授予访问 ModelState 的其他层)中的如下处理程序以捕获以下异常。请注意,我使用 AutoMapper 将 ViewModel 之间的属性复制到实体。

Entity Framework Power Tools(在解决方案资源管理器中右键单击您的项目安装后,将出现一个新的“实体框架”菜单 -> 反向工程 - 请注意它不会生成 [TimeStamp] 属性并忘记放入模式名称 - 除此之外它非常好)


[HttpPost]
public ActionResult Create(CustomerCreateViewModel customerViewModel)
{
    if (ModelState.IsValid)
    {
        try
        {
            Mapper.CreateMap();
            Customer customer = Mapper.Map(customerViewModel);

            var repository = new CustomerRepository(db);
            repository.Save(customer);
            return RedirectToAction("Edit", new { id=customer.CustomerId});
        }
        catch (DbEntityValidationException ex)
        {
            foreach (var error in ex.EntityValidationErrors.First().ValidationErrors)
            {
                this.ModelState.AddModelError(error.PropertyName, error.ErrorMessage);
            }
            return View();
        }
    }
    return View(customerViewModel);
}

I would 100% absolutely still use some POCO class. Download the DBContext generator template that will then create the code first from your model, OR use the Entity Framework Power Tools to reverse engineer an existing database. The down side to these methods though is that you won't get client side validation, only when saving it will you get the validation. You can however still add your validation attributes if you so choose for client side validation in addition using
MetaData Classes to use Data Annotations on your properties and get client side validation using the built in jQuery unobtrusive validation.

However - what we're talking about here goes against the basic design of MVC good practices anyways. Ideally your views should have ViewModels that are at times only a portion of an entity, in this case your validation attributes are still generated on your properties as DataAnnotations in MetaDataClasses.

If you feel this is all too much work and you are fine with just the server validation and have made a decision not to use ViewModels and rely on the Entity Frameworks validation- or use ViewModels and still rely on EF validation, then you will need a handler like the following in your controller (or other layer that has been given access to ModelState) to catch the following exception. Note I use AutoMapper to copy the properties between my ViewModel to my Entity.

Entity Framework Power Tools (right click in your project in solution explorer after its installed and there will be an new 'Entity Framework' menu -> Reverse Engineer - note it doesnt generate [TimeStamp] attributes and forgets to put in schema names - besides that its pretty good)


[HttpPost]
public ActionResult Create(CustomerCreateViewModel customerViewModel)
{
    if (ModelState.IsValid)
    {
        try
        {
            Mapper.CreateMap();
            Customer customer = Mapper.Map(customerViewModel);

            var repository = new CustomerRepository(db);
            repository.Save(customer);
            return RedirectToAction("Edit", new { id=customer.CustomerId});
        }
        catch (DbEntityValidationException ex)
        {
            foreach (var error in ex.EntityValidationErrors.First().ValidationErrors)
            {
                this.ModelState.AddModelError(error.PropertyName, error.ErrorMessage);
            }
            return View();
        }
    }
    return View(customerViewModel);
}

第七度阳光i 2024-12-17 09:28:42

Jon Galloway 有一篇不错的文章,名为 从现有数据库生成 EF Code First 模型类,我认为这将极大地帮助您根据您所描述的内容启动应用程序。

其次,从到目前为止构建我们自己的 MVC 应用程序来看,我发现您实际上不会经常直接使用实体框架模型。大多数时候,您最终会得到某种类型的视图模型来执行获取和发布操作。将 DataAnnotations 添加到这些类属性将使您可以轻松地在客户端进行验证。一旦您验证了客户端的数据并根据任何业务规则检查了您的实体,您就真的应该能够信任这些数据并使用 EF 来执行基本的 CRUD 工作。

祝你好运,希望这对你的项目有所帮助。

Jon Galloway has a nice article called Generating EF Code First model classes from an existing database which I think will help you greatly in getting your application up and going from what you described.

Secondly, from having built out our own MVC application so far, I've found that you're really not going to be working directly with Entity Framework models directly very often. Most of the time you'll end up with some type of view model for doing your gets and posts to. Adding DataAnnotations to those class properties will make it very easy for you to do your validations on the client side. Once you have validated the data from the client side and checked your entities against any business rules, you really should then be able to trust the data and use EF to do your basic CRUD work with.

Good luck, and hope this helps you some with your project.

自我难过 2024-12-17 09:28:42

Marius 试图告诉您的是,“代码优先”是指您的“模型”由不依赖于 .edmx 文件的流畅代码映射定义。因此,如果您使用 .edmx 文件,则您并不是在执行“代码优先”。您正在执行“数据库优先”或“模型优先”(两者都使用 .edmx)。

在您的例子中,您已经拥有一个数据库,因此您使用的是“数据库优先”方法,即使用 EF 4.1 DbContext。这不是“代码优先”(或者正如您错误地表述的那样,实体优先)。这不是语义上的争论,因为“代码优先”具有非常具体的含义。不是这样的。

现在,回答你剩下的问题。由于所有数据库访问都必须通过存储过程,因此我认为实体框架不是一个好的选择。你最好使用像 nhibernate 这样的东西,它有更好的存储过程支持。

EF 旨在以对象的形式表示关系数据模型,并生成所有自己的 sql 来访问和填充这些对象。如果您必须经历这些过程,EF 对您来说将是一场持续的艰苦战斗。

What Marius is trying to tell you is that "Code First" refers to your "model" being defined by fluent code mappings that do not rely on an .edmx file. Therefore, if you're using an .edmx file, you're not doing "code first". You're doing either "Database First" or "Model First" (both of which use the .edmx).

In your case, you already have a database, so you're using the "Database First" approach, using EF 4.1 DbContext. This is not "Code First" (or as you incorrectly stated, Entity First). This is not a semantic quibble, as "code first" has a very specific meaning. This is not it.

Now, on to the rest of your question. Since all your database access has to go through stored procedures, Entity Framework is not a good choice in my opinion. You would be better off using something like nhibernate, which has much better stored procedure support.

EF is intended to represent your relational data model in objects, and generates all its own sql to access and fill these objects. If you have to go through the sprocs, EF will be a constant uphill battle for you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文