【发布时间】:2017-05-26 15:32:50
【问题描述】:
在我的编辑页面上,我收到了这个错误:
附加一个类型的实体失败,因为另一个相同类型的实体已经具有相同的主键值。
所以,我对此进行了研究并来到this。
这让我想使用 Auto-Mapper 来简化事情。
这是我的代码:
if (db.TableName.Find(value.ID).stringProperty.Equals(value.stringProperty, StringComparison.CurrentCultureIgnoreCase))
{
Table inContextVariable = db.TableName.Find(value.ID);
Mapper.Initialize(config => config.CreateMap<ModelName, ModelName>());
Mapper.Map<ModelName, ModelName>(value, inContextVariable);
db.Entry(inContextVariable).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
这导致我出现此错误:
附加信息:操作失败:无法更改关系,因为一个或多个外键属性不可为空。当对关系进行更改时,相关的外键属性将设置为空值。如果外键不支持空值,则必须定义新关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。
这个表有 1 个外键,当我调试时外键的值为 11,所以我很难理解这个错误。
更新
想象一下,如果我有一个数据库表,其中包含包含某人信息的记录,例如:
| ID | First Name | Last Name | Email |
----------------------------------------------------------------------------
1 John Doe john.doe@test.com
2 Christopher Columbus | chris.columbus@test.com |
等等等等..现在,由于一个人只能有一个电子邮件地址,因此您必须在其他用户创建/编辑记录时采取保护措施..
例如,如果我要使用此应用程序并想创建一个帐户。我应该无法使用数据库表中已存在的电子邮件地址成功填写表单。我应该收到一条错误消息说类似
该电子邮件地址已经存在!请输入另一个电子邮件地址
代码如下:
if (db.TableName.Any(x => x.Email.Equals(value.Email, StringComparison.CurrentCultureIgnoreCase)))
{
ModelState.AddModelError("Email", "This email already exists!");
return View(value);
}
现在....当用户成功创建一个帐户..然后去编辑他们的帐户电子邮件地址到一个已经存在的东西时会发生什么?应该会出现相同的错误消息。
但是当该用户创建他们的帐户时,他们的电子邮件地址现在在数据库表中。所以当他们进入编辑页面时,使用他们的原始电子邮件,他们点击“保存”,代码将根据数据库中的所有电子邮件地址检查该电子邮件,它会看到它已经在数据库中,导致显示错误消息(请更改您的电子邮件。..等)..
因此,我需要尝试创建一种有效的方法来检查何时用户在 edit 页面上,并使用他们的原始页面点击“保存”电子邮件,它不会告诉他们更改电子邮件。
所以我有这个代码:
if (db.TableName.Find(value.ID).Email.Equals(value.Email, StringComparison.CurrentCultureIgnoreCase))
{
var inContextVariable = db.TableName.Find(value.ID);
MappingMethods.MapModelName(inContextVariable , value);
\\ without the mapping.. I receive the error saying 'Attaching an entity of type failed because another entity of the same type already has the same primary key value.'
db.Entry(inContextVariable).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
【问题讨论】:
-
我建议您在启动时而不是在使用时初始化您的映射。我们通常在 Startup.cs 中运行
AutoMapperConfig.Configure()方法,该方法会初始化映射。 -
我认为您的根本问题与 EF 的关系比任何事情都重要。尝试创建一个视图模型来容纳从 inContextVariable 到 vew 模型变量的副本和映射。然后,您可以在其他地方使用该变量而不必担心 EF。 (假设这是目标。)
-
@nurdyguy 你能提供代码以便我更好地理解吗?
-
@nurdyguy 所以创建一个与
ModelName具有完全相同属性的视图模型? -
请给我们看一下ModelName类,肯定是你映射后的外键属性为空
标签: c# asp.net-mvc automapper