Entity framework EF5附加实体验证
模式中的EF5和非空字符串有点神秘。例如,假设我们有一个简单的用户表:Entity framework EF5附加实体验证,entity-framework,Entity Framework,模式中的EF5和非空字符串有点神秘。例如,假设我们有一个简单的用户表: CREATE TABLE Users ( UserID INT PRIMARY KEY NOT NULL IDENTITY(1,1), UserName VARCHAR(50) NOT NULL, UserFirst VARCHAR(50) NULL, UserLast VARCHAR(50) NULL ) 。。。我创建了一个POCO类来表示它。这一切都很好。我可以检索和创建数据,但是更新造成了一些
CREATE TABLE Users
(
UserID INT PRIMARY KEY NOT NULL IDENTITY(1,1),
UserName VARCHAR(50) NOT NULL,
UserFirst VARCHAR(50) NULL,
UserLast VARCHAR(50) NULL
)
。。。我创建了一个POCO类来表示它。这一切都很好。我可以检索和创建数据,但是更新造成了一些严重的痛苦。假设我想更新给定用户的名字:
User user = new User { UserID = 12345 };
context.Users.Attach(user);
user.FirstName = "SomethingElse";
context.SaveChanges();
这应该行得通。附件后,不可为空的用户名
为空。这应该很好-我没有试图更改它,更改检测表明该值未更改。但是,当我调用SaveChanges
时,会抛出一个DB验证异常,说明用户名
无效
因此,从这一点来看,有两个问题:
context.Configuration.ValidateOnSaveEnabled
,但我不认为简单地关闭验证是一个有效的答案。还有其他类似的选择吗您说您想更新一个用户,但您的示例代码是创建一个Id为12345的新用户,然后附加它。您的代码所做的是创建一个全新的实体,将一个不可为null的字段保留为null,并尝试保存到数据库,这会引发错误 您是否打算检索ID为12345的现有用户?然后,您应该从数据库中获取该实体,然后更新属性,而不是创建新实体
User user = context.Users.First(u => u.UserID == 12345);
user.FirstName = "SomethingElse";
context.SaveChanges();
编辑
当您在附加之后修改FirstName属性时,EF会将整个实体标记为dirty,因此它会尝试更新所有内容
如果只想更新名字,则需要更改代码(从a):
我明白你的意思,但我不同意。从
Attach
:“…实体被置于未更改状态,就像它是从数据库中读取的一样。”换句话说,UserName
为null这一事实应该是无关紧要的,因此,验证应该是按属性,而不是按对象。(此外,如果您设置了相同的场景,但在EDMX中将默认值设置为空字符串,则无需在保存时设置用户名
,并且空字符串不会持久化。)我还不清楚的是,当实体显式公开IsModified
时,为什么该实体被标记为脏批发。在我看来,应该只检查已修改的字段,在我原来的情况下,只修改了一个字段。然而,仔细考虑之后,试图使上下文足够智能以零碎地保存实体——特别是从代码优先的角度来看——将是相当令人畏惧的。使用聪明的模板是可行的,但我不确定是否值得为此项目付出努力。
var user = new User { UserID = 12345, FirstName = "SomethingElse" };
using (var db = new MyEfContextName())
{
context.Users.Attach(user);
context.Entry(user).Property(x => x.FirstName).IsModified = true;
context.SaveChanges();
}