Breeze 正在尝试更新计算的数据库列
Posted
技术标签:
【中文标题】Breeze 正在尝试更新计算的数据库列【英文标题】:Breeze is trying to update a computed database column 【发布时间】:2013-03-28 15:08:53 【问题描述】:一位朋友报告了计算列、实体框架和 Breeze 的问题
我们有一个表,其中包含由数据库计算的“FullName”列。创建新的
Person
时,Breeze 将FullName
属性值发送到服务器,即使它根本没有设置,并且在尝试插入新的Person
实例时会触发错误。数据库抛出此异常:
The column "FullName" cannot be modified because it is either a computed column or is the result of a UNION operator.
以下是 SQL 表定义的相关部分:
创建表 [dbo].[Person]( [ID] [bigint] IDENTITY(1,1) 非空, [名字] [varchar](100) 空值, [中间名] [varchar](100) NULL, [姓氏] [varchar](100) 非空, [FullName] AS ((([Patient].[LastName]+',') + isnull(' '+[Patient].[FirstName],'')) + isnull(' '+[Patient].[MiddleName] ,'')), ...我的朋友告诉我相应的“代码优先”类看起来像这样:
公共类人 公共 int ID get;放; 公共字符串名字 get;放; 公共字符串 MiddleName get;放; 公共字符串姓氏get;放; 公共字符串 FullName get;放; ...这个问题的答案解释了问题并提供了解决方案。
【问题讨论】:
【参考方案1】:设计问题
看到这个的每个人都想知道为什么FullName
有一个计算列,其次,为什么这个属性会暴露给客户端。
让我们假设计算列是有充分理由的,模型有充分理由从表中获取值而不是计算值本身,并且有充分理由将其发送给客户端而不是让客户计算它。这是他告诉我的;
“我们需要在查询中包含
FullName
”
生活有时会这样。
后果
请注意,FullName
属性有一个公共设置器。 Person
类的 EF 元数据生成器无法判断这是一个只读属性。 FullName
看起来就像 LastName
。元数据说“这是正常的读/写属性。”
Breeze 也没有发现差异。客户端应用程序可能不会触及此属性,但 Breeze 在创建新的Person
时必须为其发送一个值。回到服务器上,Breeze EFContextProvider
认为它应该在创建 EF 实体时传递该值。灾难的舞台已经准备好。
如果 (a) 您无法更改表格并且 (b) 您无法更改模型的 FullName
属性定义,您该怎么办?
解决方案
英孚需要您的帮助。您应该告诉 EF 这实际上是一个数据库计算属性。您可以使用 EF fluent 接口或使用此处显示的属性:
[DatabaseGenerated(DatabaseGeneratedOption.Computed)] 公共字符串全名 获取;放;添加这个属性,EF 知道这个属性是只读的。它将生成适当的元数据,您可以干净地保存新的Person
。省略它,你会得到异常。
请注意,这仅对 Code First 是必需的。如果他首先生成了模型 Database First,EF 知道该列已计算并且不会尝试设置它。
请注意与商店生成的密钥类似的问题。整数键的默认值是“存储生成的”,但 Guid 键的默认值是“客户端生成的”。如果在您的表中,数据库实际上设置了 Guid,则必须使用 [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 标记ID
属性
【讨论】:
以上是关于Breeze 正在尝试更新计算的数据库列的主要内容,如果未能解决你的问题,请参考以下文章