如何确保 Linq to Sql 不会覆盖或违反不可为空的 DB 默认值?
Posted
技术标签:
【中文标题】如何确保 Linq to Sql 不会覆盖或违反不可为空的 DB 默认值?【英文标题】:How do I ensure Linq to Sql doesn't override or violate non-nullable DB default values? 【发布时间】:2008-10-14 15:44:37 【问题描述】:我有一个带有这些字段的表的 SQL Server 数据库:
bit
,默认值为 1,NOT NULL
。
一个smalldatetime
,默认值为gettime()
,NOT NULL
。
一个没有默认值的int
,IDENTITY
,NOT NULL
。
当我为此表生成 Linq to SQL 时,会发生以下情况:
bit
没有得到特殊处理。
smalldatetime
没有得到特殊处理。
int
被标记为IsDbGenerated
。
这意味着当我使用 Linq to SQL 进行插入时,会发生以下情况:
bit
将作为 0 发送,覆盖默认值。 对吗?
smalldatetime
将作为未初始化的System.DateTime
发送,在 SQL Server 中产生错误,因为它不属于 SQL Server smalldatetime 范围。 对吗?
IsDbGenerated
int
将不会被发送; DB 将生成一个值,然后 Linq to SQL 将读回该值。
我必须进行哪些更改才能使此方案生效?
总结一下:我想要具有 DB 分配的默认值的不可空字段,但我不想要它们 IsDbGenerated
,如果这意味着在使用 Linq to SQL 进行更新或插入时我无法为它们提供值。我也不想要他们IsDbGenerated
,如果这意味着我必须将 Linq 生成的代码手动修改为 SQL。
编辑:答案似乎是这是当前 Linq to SQL 的一个限制。
【问题讨论】:
重复:***.com/q/1120858/11683(不投票结束,两者同样有用)。 【参考方案1】:Linq-To-Sql 生成的类不使用默认值约束。
也许在未来,但问题是约束并不总是简单的值,它们也可以是像GetDate()
这样的标量函数,所以 linq 必须知道如何翻译这些值。简而言之,它甚至没有尝试。它也是一种非常特定于数据库的类型。
CodeProject - Setting Default Values for LINQ Bound Data 详细描述了您遇到的问题
【讨论】:
"linq 必须知道如何翻译这些" - 为什么?它可以只允许在创建/更新时不传递任何内容,然后再将它们读回。这就是 IsDbGenerated 字段的工作方式,除了它们在 Linq 端的只读状态。 当然,它可以允许它,但它不允许。 IsDbGenerated 仅适用于此时的关键列。 “linq 会以某种方式......”只是我对为什么会出现这种情况的看法。 似乎 IsDbGenerated 现在也可用于非键列。【参考方案2】:我遇到了同样的问题,bzlm,并得出了同样的结论。使用 Linq To Sql 获取具有 DB 分配的默认值的不可空字段根本没有好方法。
我所采用的解决方法是添加一个 SetDefaults() 方法,该方法与 CodeProject 上的 Robert Paulson 链接的方法非常相似,并在我的表实体基类的默认构造函数中调用它。它对我很有效,因为 95% 的时间,我设置的是 0、空字符串或 getdate()。
【讨论】:
【参考方案3】:这意味着当我使用 Linq to SQL 进行插入时,以下将 发生:
该位将作为 0 发送,覆盖默认值。正确的? - 正确 smalldatetime 将作为未初始化的 System.DateTime 发送, 在 SQL Server 中产生错误,因为 它不属于 SQL Server 小日期时间范围。正确的? - 发送的是 DateTime.MinValue 不会发送 IsDbGenerated int;数据库将生成一个值 然后Linq to SQL 会读回。 - 如果设置了 DB generated,则该值由数据库创建,如果没有,则 Linq 期望用户设置该值。
如果您不使用自动属性,最好将它们设置在对象的构造函数中或私有字段中。
【讨论】:
听起来你在说 SQL Server 值中字段的默认值不可能与 Linq To SQL 结合使用。这是正确的吗? 有可能,但事后您无法更改它们。如果您希望能够更改它们,那么您应该在构造函数中创建它们。 对不起,我不明白。什么是可能的?在什么事实之后不能改变什么?是否可以让 Linq To SQL 执行插入并在使用的数据库中指定“默认值”? 不要使用构造函数,有一个特殊的分部方法叫做 OnCreate 。看到这个问题:***.com/questions/82409/… 其实是OnCreated。 Longhorn213 的回答非常混乱,而且他/她似乎也无缘无故地编辑了我原来的问题。忽略他/她。【参考方案4】:您可以为您的数据上下文(部分类)创建另一个文件,然后使用 InsertYOURENTITY 和 UpdateYOURENTITY 部分方法来检查您的属性并分配正确的值。 在您的代码之后调用 ExecuteDynamicInsert 或 ExecuteDynamicUpdate 并设置好。
【讨论】:
实际上,在 BLL 中执行此操作的推荐方法是为实体实现部分方法 OnCreated(),而不是您建议的方法。不过,这与我的问题无关。我的问题是关于 SQL Server 中的默认值,而不是 BLL 中的默认值。以上是关于如何确保 Linq to Sql 不会覆盖或违反不可为空的 DB 默认值?的主要内容,如果未能解决你的问题,请参考以下文章
WP7 Linq To SQL(SQL CE) IDataErrorInfo
使用DISTINCT时,LINQ to SQL不生成ORDER BY?
LINQ to SQL 或任何其他启用了 LINQ 的 ORM 是不是支持许多关联过滤?