繁体   English   中英

当属性验证依赖于另一个属性值时,如何使用元数据验证实体框架 4 Model?

[英]How do I Validate An Entity Framework 4 Model Using Metadata When The Property Validation Is Dependent on Another Property Value?

我有一个实体框架 model ,我正在尝试添加验证,但我发现自己在这里遇到了一些问题 22。

我在一个单独的文件中有一个部分 class 与生成的实体 model 相关,看起来像这样......

[MetadataType(typeof(cmsNodeMetadata))]
public partial class cmsNode : IDataErrorInfo
{  
    ... Code ....


    #region IDataErrorInfo

    private readonly Dictionary<string, string> _errors = new Dictionary<string, string>();
    private readonly Entities _db = new Entities();
    public string this[string columnName]
    {
        get
        {
            if (_errors.ContainsKey(columnName))
                return _errors[columnName];
            return string.Empty;
        }
    }

    public string Error { get; private set; }

    partial void OnNameChanging(string value)
    {
        var valueIsUnique = (from n in _db.cmsNodes
                             where n.ParentId == ParentId
                                && n.Name.Trim().ToLower() == value.Trim().ToLower()
                             select n.Name).Count() == 0;

        if (!valueIsUnique)
        {
            _errors.Add("Name", "The name must be unique");
        }
    }

    #endregion  

}

...并且我在单独的 class 中添加了验证,效果很好。

public class cmsNodeMetadata
{
    [StringLength(150), Required]
    [Display(Name = "Name")]
    public string Name;
}

我使用 MVC 3 和我的 controller 使用这个 class 看起来像这样......

[HttpPost]
public ActionResult Edit(cmsNode cmsnode)
{
    if (ModelState.IsValid)
    {
        var obj = _db.cmsNodes.Single(c => c.Id == cmsnode.Id);
        obj.Name = cmsnode.Name;
        obj.Alias = cmsnode.Name.Slugify(150);
        _db.SaveChanges();
        return Content(Boolean.TrueString);
    }
    return Content("Please review your form");
}

我使用这个 class 的观点看起来像这样......

@model Project.com.Admin.Models.cmsNode

@using (Ajax.BeginForm("Create", "Node", null, new AjaxOptions
{
    UpdateTargetId = "create-message",
    InsertionMode = InsertionMode.Replace,
    HttpMethod = "POST",
    OnSuccess = "createSuccess"
}, new { @id = "createNodeForm" }))
{
    @Html.ValidationSummary(true)
    <div id="create-message" class="error invisible"></div>
    <fieldset>
        <legend>Create New Navigation Tree Node</legend>
        <div class="editor-label">
            @Html.LabelFor(model => model.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Name)
            @Html.ValidationMessageFor(model => model.Name)
        </div>
        @Html.HiddenFor(model => model.ParentId)
        @Html.HiddenFor(model => model.Alias)
    </fieldset>
}

好的,那么问题来了。 我需要向 this(cmsNode) class 添加一些自定义验证,以确保名称尚未被具有相同 ParentId 的任何其他节点使用。

为此,我需要获取名为 ParentId 的实例成员的句柄。 不幸的是,我无法弄清楚如何处理我从 cmsNodeMetadata class 验证的实例。

因此,我尝试通过覆盖我的 cmsNode class 中名称属性的 onChanging 方法并在那里添加验证来改变我的方法,但这会导致另一个问题。 虽然我可以使用验证的覆盖方法检查名称属性,但当名称从视图中返回未设置时,我会遇到异常,因为我的实体 model 不排除 Name 属性的 null 值,我无法捕获它,因为视图的内容在我的controller的输入参数中转换为model类型。

然后我尝试同时使用 MetadatatType 和 onChanging 验证方法,但忽略 onChanging 方法。

我意识到我可以通过以下方式解决这个问题:

  • I could change the return type of the controller to FormCollection collection, a dto object, or define input properties directly and utilize and then create the object in the controller after I check for a null value which is fine.

我只是想知道我错过了什么吗? 有没有办法使用 ValidationAttributes 验证属性并检查重复名称? 我可以阻止 Null 从我的视野中回来吗? 为什么实体框架中的 onChanging 方法没有 Cancel 选项来防止在验证失败时设置成员? 谢谢你的帮助!

跨实体验证不是实体本身的一部分,因为它不是它的责任。 因此,您不应期望该实体或放置在该实体上的任何验证器会执行此验证。 您的实体不应进行此验证的另一个原因是它需要上下文来进行查询,而实体 (POCO) 不应依赖于上下文。

谁负责该验证? 根据您的应用程序体系结构,一旦实体本身有效,将在您的IsValid块内调用单独的方法。 此方法将使用 EF 并查询是否存在相同的名称。 如果您接近域驱动设计,则验证应该在父级中,这将验证其子级是否具有相同的名称(这意味着它将加载子级)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM