如何确保 Linq to Sql 不会覆盖或违反非空数据库默认值?

14
我有一个SQL Server数据库,其中有一个具有以下字段的表格:
  1. 一个默认值为1且为NOT NULLbit类型。
  2. 一个默认值为gettime()且为NOT NULLsmalldatetime类型。
  3. 一个没有默认值、为IDENTITY且为NOT NULLint类型。
当我生成此表格的 Linq to SQL 时,会发生以下情况:
  1. bit 没有被特殊处理。
  2. smalldatetime 没有被特殊处理。
  3. int 被标记为 IsDbGenerated
这意味着使用 Linq to SQL 进行插入时,以下情况将发生:
  1. bit 将被发送为0,覆盖默认值。对吗?
  2. smalldatetime 将被发送为未初始化的System.DateTime,在 SQL server 中产生错误,因为它不符合 SQL Server smalldatetime 范围。对吗?
  3. IsDbGeneratedint 不会被发送;数据库将生成一个值,然后 Linq to SQL 会将其读回。
我需要做哪些更改才能使这种情况正常工作? 总结一下:我想要具有分配给 DB 的默认值的非空字段,但如果这意味着使用 Linq to SQL 时无法为它们提供值进行更新或插入,则不希望它们成为 IsDbGenerated。如果这意味着我必须手动修改由 Linq to SQL 生成的代码,则也不希望它们成为 IsDbGenerated
编辑:答案似乎是这是当前 Linq to SQL 的限制。

重复:https://dev59.com/oHNA5IYBdhLWcg3wBpDs(不投票关闭,两个都同样有用)。 - GSerg
4个回答

5
Linq-To-Sql生成的类无法获取默认值约束。这可能会在未来得以解决,但问题在于约束并不总是简单的值,它们也可以是像"GetDate()"这样的标量函数,因此Linq需要知道如何翻译它们。简而言之,它甚至都没有尝试。这也是一种非常特定于数据库的类型。
您可以编写代码生成器来创建实体部分类,从中提取默认值约束。或者,您的业务层代码可以从xml文件中的构造函数设置默认值,您只需要保持xml文件最新即可。您还可以在提交更改到数据库之前检查ChangeSet并模拟sql添加默认值,而不是在构造函数中执行工作。
您遇到的问题在CodeProject - Setting Default Values for LINQ Bound Data中有详细描述。

1
"linq 在某种程度上必须知道如何翻译它们" - 为什么? 它可以只允许在创建/更新时不传递任何内容,然后在之后读取它们。 这就是 IsDbGenerated 字段的工作方式,除了它们在 Linq 端的只读状态。 - bzlm
当然,它可能允许这样做,但实际上并没有。IsDbGenerated目前仅适用于关键列。 "linq would somehow ..."只是我的看法,为什么会出现这种情况。 - Robert Paulson
似乎现在IsDbGenerated也适用于非主键列了。 - Make it useful Keep it simple

3

我遇到了和bzlm一样的问题,并得出了相同的结论。使用Linq To Sql无法很好地处理具有DB分配默认值的非可空字段。

我的解决方法是添加一个SetDefaults()方法,与Robert Paulson在CodeProject上链接的方法非常相似,并在我的表实体基类的默认构造函数中调用它。对我来说效果很好,因为95%的时间,我设置的是0、空字符串或getdate()。


2
这意味着当我使用Linq to SQL进行插入时,将会发生以下情况:
  1. bit将被发送为0,覆盖默认值。对吗? - 正确
  2. smalldatetime将作为未初始化的System.DateTime发送,这将在SQL Server中产生错误,因为它不在SQL Server smalldatetime范围内。对吗? - 发送的是DateTime.MinValue
  3. IsDbGenerated int不会被发送;数据库将生成一个值,然后Linq to SQL将读回该值。- 如果设置了DB generated,则该值由数据库创建,否则Linq期望用户设置该值。
您最好在对象的构造函数或私有字段上设置它们,如果您没有使用自动属性。

听起来你是在说SQL Server字段中的默认值无法与Linq To SQL结合使用,这是正确的吗? - bzlm
可以实现,但创建后就不能更改了。如果希望能够修改它们,则应在构造函数中创建它们。 - David Basarab
抱歉,我不明白。什么是可能的?在什么事实之后不能改变什么?是否可以使Linq To SQL执行插入并使用DB中指定的“默认值”? - bzlm
不要使用构造函数,有一个特殊的部分方法叫做OnCreate来完成这个任务。请参考这个问题:https://dev59.com/HkXRa4cB1Zd3GeqPpi0Y。 - Sam
实际上,应该是OnCreated。Longhorn213的回答非常令人困惑,而且他/她似乎毫无理由地编辑了我的原始问题。请忽略他/她。 - bzlm

0
你可以为你的数据上下文(partial class)创建另一个文件,然后使用InsertYOURENTITY和UpdateYOURENTITY部分类来检查你的属性并分配正确的值。 在你的代码之后调用ExecuteDynamicInsert或ExecuteDynamicUpdate,就完成了。

实际上,在BLL中建议实现实体的部分类方法OnCreated()而不是您提出的方法。 但是,这与我的问题无关。 我的问题是关于SQL Server中的默认值,而不是BLL中的。 - bzlm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接