两个在一个实体中检查IValidatableObject

时间:2013-08-15 03:43:09

标签: asp.net-mvc entity-framework asp.net-mvc-4 ivalidatableobject

Project的本质是,必须创建它来检查是否已经存在具有相同名称的实体。在编辑需要时,例如检查,但请记住,可以匹配实体的旧名称和新名称。 您还需要显示错误消息。为此,我使用接口IValidatableObject,但不知道如何告诉Validate方法当前正在编辑或创建对象

3 个答案:

答案 0 :(得分:0)

DbContext.ValidateEntityIDictionary<Object, Object> items作为第二个参数。您可以在那里传递任何数据,并且您传递的数据将传递到IValidatableObject.Validate

中的ValidationContext.Items

答案 1 :(得分:0)

假设你参考检查EF不能为你做 这实际上很难检查。在将实体添加到上下文后,您正在检查它。它不应该检查自己,需要考虑尚未保存的上下文中的其他项。以及DB。有3种组合加上自我识别。当ID为空/新时,在LOCAL中记录实体记录,即多个新插入需要仔细编码。 (考虑使用临时ID)

尚未保存的条目应该在上下文中

Context.Set<TPoco>().Local

从数据库获取数据并保存在临时列表中。但不要放在上下文中。 或者使用SECOND上下文。

 var matchingSet = Context.Set<TPoco>().AsNoTracking()   // not into context...
                      .Where(t=>t.field == somevalue).ToList(); 

那么DB上的逻辑和实际重复是怎么回事。逻辑副本在字段上是重复的,没有唯一索引,从业务角度来看应该是唯一的。

如果你想查看那些......

您需要读取数据库....但是如果这些记录当前正在被更改,您不能只将它们放入上下文中。你会覆盖他们。 但是如果逻辑键值的值发生了变化呢? 在DB上的记录上导致逻辑重复的某些内容可能在保存或反之后不再是重复。这仍然是一个重复吗?

因此,您需要决定如何匹配LOCAL与已加载的记录。 即检查LOCAL并匹配数据库记录并判断如果记录同时存在,仅存在本地或仅存在数据库,该怎么办。  只有本地和DB才很容易 但两者都是......这是您的业务流程决策。

答案 2 :(得分:0)

在编辑和创建操作中使用方法ModelState.AddModelError(string,string)解决问题。

[HttpPost]
[HandleError(View="AjaxError")]
public ActionResult Edit(ProjectsViewData data)
{
    if (ModelState.IsValid)
    {
        if (!ContainsProject(data.CurrentObject.Name))
        {
            db.Projects.Attach(data.CurrentObject);
            db.ObjectStateManager.ChangeObjectState(data.CurrentObject, EntityState.Modified);
            db.SaveChanges();
            return Projects(data);
        }
        else
        {
            int projectId = (from p in db.Projects
                                where p.Name == data.CurrentObject.Name
                                select p.ProjectID).FirstOrDefault();
            if (projectId == data.CurrentObject.ProjectID)
            {
                db.Projects.Attach(data.CurrentObject);
                db.ObjectStateManager.ChangeObjectState(data.CurrentObject, EntityState.Modified);
                db.SaveChanges();
                return Projects(data);
            }
            else
            {
                ModelState.AddModelError("Name", Localizer.ProjectAlreadyExists);
            }
        }
    }

    data.ObjectToEdit = data.CurrentObject;
    return Projects(data);
}

[HttpPost]
[HandleError(View = "AjaxError")]
public ActionResult Create(ProjectsViewData data)
{
    if (ModelState.IsValid)
    {
        if (!ContainsProject(data.CurrentObject.Name))
        {
            db.Projects.AddObject(data.CurrentObject);
            db.SaveChanges();
            return Projects(data);
        }
        else
        {
            ModelState.AddModelError("Name", Localizer.ProjectAlreadyExists);
        }
    }

    data.ObjectToAdd = data.CurrentObject;
    return Projects(data);
}

帮助方法:

private bool ContainsProject(string projectName)
{
    if (projectName != null)
    {
        projectName = Regex.Replace(projectName.Trim(), "\\s+", " ");
        List<string> projects = new List<string>();
        var projectNames = (from p in db.Projects
                            select p.Name.Trim()).ToList();
        foreach (string p in projectNames)
        {
            projects.Add(Regex.Replace(p, "\\s+", " "));
        }
        if (projects.Contains(projectName))
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    else
    {
        return false;
    }
}