是Project的本质,创建它需要检查是否已经存在同名实体。当编辑需要检查时,但要记住实体的新旧名称是可以匹配的。您还需要显示错误消息。为此,我使用 IValidatableObject 接口,但不知道如何告诉 Validate 方法当前正在编辑或创建对象
3 回答
DbContext.ValidateEntity takes the IDictionary<Object, Object> items
as the second parameter. You can pass any data there and the data you pass will be passed to IValidatableObject.Validate
in the ValidationContext.Items
假设您参考检查 EF 无法为您做的事情。
这实际上很难检查。您在将实体添加到上下文后对其进行检查。它不应该检查自己,需要考虑上下文中尚未保存的其他项目。以及数据库。有几个 3 组合加上一个自我识别。当 ID 为空白/新时,在 LOCAL 中记录一个实体记录,即多个新插入需要仔细编码。(考虑使用临时 ID)
尚未保存的条目应该在上下文中
Context.Set<TPoco>().Local
并从数据库中获取数据并保存在临时列表中。但不要放在上下文中。或者使用第二个上下文。
var matchingSet = Context.Set<TPoco>().AsNoTracking() // not into context...
.Where(t=>t.field == somevalue).ToList();
那么数据库上的逻辑和实际重复呢?逻辑重复是没有唯一索引的字段上的重复,从业务角度来看应该是唯一的。
如果你想检查那些...
您需要阅读数据库......但如果这些记录当前正在更改,您不能只将它们放入上下文中。你会覆盖它们。但是,如果逻辑键值的值发生了变化怎么办?导致数据库记录上的逻辑重复的某些东西一旦保存就可能不再是重复,反之亦然。这仍然是一个骗局吗?
因此,您需要决定如何匹配 LOCAL 与加载的记录。即检查本地和匹配的数据库记录,并决定如果记录在两者中,只有本地或只有数据库,该怎么办。仅本地和仅数据库很容易。
但在这两者中......这是您的业务流程决策。
在编辑和创建操作中使用方法 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;
}
}