在使用ADO.NET Entity Framework 4的SQL Server中使用“而不是”触发器的视图中插入记录时,我收到无效操作异常。 错误消息显示:
{“对数据库的更改已成功提交,但更新对象上下文时发生错误.ObjectContext可能处于不一致状态。内部异常消息:定义EntityKey的键值对不能为null或空。参数名称:记录“}
@ at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options)
at System.Data.Objects.ObjectContext.SaveChanges()
在这个简化的例子中,我创建了两个表,Contacts和Employers,以及一个Contacts_x_Employers视图,它允许我一次在这两个表中插入或检索行。表只有Name和ID属性,视图基于两者的连接:
CREATE VIEW [dbo].[Contacts_x_Employers]
AS
SELECT dbo.Contacts.ContactName, dbo.Employers.EmployerName
FROM dbo.Contacts INNER JOIN dbo.Employers
ON dbo.Contacts.EmployerID = dbo.Employers.EmployerID
并且有这个触发器:
Create TRIGGER C_x_E_Inserts
ON Contacts_x_Employers
INSTEAD of INSERT
AS
BEGIN
SET NOCOUNT ON;
insert into Employers (EmployerName)
select i.EmployerName
from inserted i
where not i.EmployerName in
(select EmployerName from Employers)
insert into Contacts (ContactName, EmployerID)
select i.ContactName, e.EmployerID
from inserted i inner join employers e
on i.EmployerName = e.EmployerName;
END
GO
.NET代码如下:
使用(var Context = new TriggersTestEntities()) { Contacts_x_Employers CE1 = new Contacts_x_Employers(); CE1.ContactName =“J”; CE1.EmployerName =“T”; Contacts_x_Employers CE2 = new Contacts_x_Employers(); CE1.ContactName =“W”; CE1.EmployerName =“C”; Context.Contacts_x_Employers.AddObject(CE1); Context.Contacts_x_Employers.AddObject(CE2); Context.SaveChanges(); //行有错误 }
SSDL和CSDL(视图节点):
<EntityType Name="Contacts_x_Employers">
<Key>
<PropertyRef Name="ContactName" />
<PropertyRef Name="EmployerName" />
</Key>
<Property Name="ContactName" Type="varchar" Nullable="false" MaxLength="50" />
<Property Name="EmployerName" Type="varchar" Nullable="false" MaxLength="50" />
</EntityType>
<EntityType Name="Contacts_x_Employers">
<Key>
<PropertyRef Name="ContactName" />
<PropertyRef Name="EmployerName" />
</Key>
<Property Name="ContactName" Type="String" Nullable="false" MaxLength="50" Unicode="false" FixedLength="false" />
<Property Name="EmployerName" Type="String" Nullable="false" MaxLength="50" Unicode="false" FixedLength="false" />
</EntityType>
可以在ftp://JulioSantos.com/files/TriggerBug/的TestViewTrggers.zip中找到用于重新创建整个应用程序的Visual Studio解决方案和SQL脚本。 我感谢您提供的任何帮助。我已经花了几天时间研究这个问题。
答案 0 :(得分:1)
当我尝试使用“而不是插入”和“而不是更新”触发器在视图中插入行时,我偶然发现了同样的问题。
我认为我找到了一个解决方案:当visual studio的向导在您的模型中删除您的视图时,它会在某些属性(可能是您实体的键)上添加StoreGeneratedPattern =“Identity”。
在常规表上生成请求时,此属性告诉实体框架期望返回一个ID,因此它会在插入的末尾附加一个select scope_identity()。
现在有了可更新的视图,scope_identity被搞砸了,因为插入发生在另一个范围内并且它返回null,因此插入失败。
如果从模型中删除此StoreGeneratedPattern =“Identity”,实体框架不会附加select scope_identity(),并且插入工作正常。
我希望这可以解决你的问题,而且不会太晚。
干杯