6

我有一个视图模型,它应该检查新实体的标签是否唯一(尚未在数据库中)。

目前我已经在视图模型类中完成了它:

     public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (PowerOrDuty != null)
        {
            if (PowerOrDuty.Identifier == null)
            {
                using (var db = new PowersAndDutiesContext()) 
                {
                    var existingLabels = db.PowersAndDuties.Select(pod => pod.Label);
                    if (existingLabels.Contains(PowerOrDuty.Label))
                    {
                        yield return new ValidationResult("Cannot create a new power or duty because another power or duty with this label already exists");
                    }
                }                    
            }
           ......

请注意,这是一个小型内部应用程序,数据库很小,我的时间有限,所以代码并不完美。

我觉得从视图模型访问数据库可能是一种不好的做法。视图模型应该直接访问数据库吗?它应该能够调用存储库来获取可用的标签吗?是否应该在控制器中进行需要数据库访问的验证?

4

4 回答 4

6

视图模型应该直接访问数据库吗?

我认为应该不惜一切代价避免这种情况

它应该能够调用存储库来获取可用的标签吗?

这不是 ViewModel 关心的问题。这会在您的 ViewModel 测试中引入一些复杂性(几乎不需要)我想这是麻烦来的迹象。

是否应该在控制器中进行需要数据库访问的验证?

也许,如果“DB”是指“存储库”。但是我想到的是一个单独的自定义验证类,您将能够(取消)插入、测试和重用,在另一个控制器中进行 ajax 验证等

于 2013-11-08T13:57:40.247 回答
1

我认为从 VM 访问数据库并没有错…… AFAIK 它并没有破坏 MVC 概念(因为它是一个表示层概念)。也就是说,如果您有服务层提供的 Validate 方法可能会更好。

但是所有与 ViewModel 内容相关的逻辑,最好保存在 VM 中而不是 Controller 中。更清洁的控制器更好。

于 2013-11-08T13:28:36.273 回答
1

我个人喜欢 ViewModels 贫乏——只是带有属性的类。

对于像这样的自定义服务器端验证,我更喜欢它在服务中使用,在控制器中使用服务,甚至在自定义验证器之后。

使用自定义验证器,您甚至可以(可选)远程执行验证。虽然这有点复杂,但我使用通用远程验证器完成了它,该验证器使用 Ajax 操作方法来执行验证,并通过客户端验证器和远程验证器连接它(以确保你有你的验证逻辑在单一方法中)。

但是无论你走哪条路,我认为将所有逻辑排除在 ViewModel 之外是更常见的——而且在我看来,更干净。即使在一个简单的应用程序中,您的 ViewModel 对您的数据库上下文也应该是哑巴的。理想情况下,只有服务(不一定是 Web 服务,而只是一个抽象层)知道您的数据库上下文。

对我来说,无论应用程序的大小如何,都应该这样做。我认为付出的努力和复杂性(它只会为您的解决方案添加另一个程序集)值得您获得抽象。以后,如果您碰巧决定从另一个应用程序使用您的服务,或者如果您决定交换您的数据库上下文,那么使用该抽象会更容易。

于 2013-11-08T13:33:26.173 回答
1

您的视图模型不应与您的上下文相关联,它只关心显示数据并在提交后对其进行验证。您可以执行必填字段或范围内的值等验证,但您无法知道数据库中是否已存在标签。

您也不能在显示表单之前获取“禁止标签”列表,以便之后测试您的标签,因为在此期间该列表可能已更改(另一个用户更新您的数据库)。

在我看来,模型级别的验证应该关注它可以在不了解数据源的情况下验证的内容,并让您的数据库通知您错误,例如在具有唯一约束的字段中提交重复值。您将捕获来自数据库的异常以查找此类错误,并相应地管理它们。

无论如何,我认为对于这样的问题没有直接的答案。

于 2013-11-08T13:33:44.740 回答