[英]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 方法。
我意识到我可以通过以下方式解决这个问题:
我只是想知道我错过了什么吗? 有没有办法使用 ValidationAttributes 验证属性并检查重复名称? 我可以阻止 Null 从我的视野中回来吗? 为什么实体框架中的 onChanging 方法没有 Cancel 选项来防止在验证失败时设置成员? 谢谢你的帮助!
跨实体验证不是实体本身的一部分,因为它不是它的责任。 因此,您不应期望该实体或放置在该实体上的任何验证器会执行此验证。 您的实体不应进行此验证的另一个原因是它需要上下文来进行查询,而实体 (POCO) 不应依赖于上下文。
谁负责该验证? 根据您的应用程序体系结构,一旦实体本身有效,将在您的IsValid
块内调用单独的方法。 此方法将使用 EF 并查询是否存在相同的名称。 如果您接近域驱动设计,则验证应该在父级中,这将验证其子级是否具有相同的名称(这意味着它将加载子级)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.