【问题标题】:Pass a NULL value to DateTime Field in LINQ将 NULL 值传递给 LINQ 中的 DateTime 字段
【发布时间】:2011-06-12 14:53:12
【问题描述】:

我的数据库表是这样的

CREATE TABLE MYBUDGET.tbl_CurrentProperty
(
    [PropID]            INT             NOT NULL  IDENTITY(1,1),
    [UpdatedOn]         DATETIME        NOT NULL,
    [Amount]            MONEY           NOT NULL,
    [Remarks]           VARCHAR(100)    NOT NULL,
)
ALTER TABLE MYBUDGET.tbl_CurrentProperty ADD CONSTRAINT PK_CurrentProperty_PropID PRIMARY KEY ([PropID])
ALTER TABLE MYBUDGET.tbl_CurrentProperty ADD CONSTRAINT DF_CurrentProperty_UpdatedOn DEFAULT (DATEADD(MINUTE,30,DATEADD(HOUR, 5, GETUTCDATE()))) FOR [UpdatedOn]
ALTER TABLE MYBUDGET.tbl_CurrentProperty ADD CONSTRAINT CK_CurrentProperty_Amount CHECK([Amount] > -1)
GO

我正在使用 LINQ to SQL。在 C# 中,我只需要传递 [Amount] 和 [Remarks] 字段,其他字段必须使用它们的默认值([PropID] 和 [UpdatedOn])。

在 C# 中,我创建 tbl_CurrentProperties 对象,如下所示,

tbl_CurrentProperties currentProperties = new tbl_CurrentProperties();
currentProperties.Amount = 50.00M;
currentProperties.Remarks = "remarks";

然后将对象提交到数据上下文。但是在这里,Linq 为 UpdatedOn 字段分配了'1/1/0001 12:00:00 AM'。但这违反了 SQL 日期时间范围1/1/1753 12:00:00 AM and 12/31/9999 11:59:59 PM 并发生异常。此外,我无法为 DateTime 字段手动分配 NULL 值,因为它是不可为空的类型。无论如何,我需要这样做才能使用其默认约束。我该怎么做?


PS:我想这样使用它,因为我的数据库是在线的,而用户位于不同的位置。所以如果我使用 DateTime.Now,用户机器中的时间可能是错误的,它会在 DB 中插入一个错误的值。我需要始终使用 SQL 服务器时间。

【问题讨论】:

  • 当然,如果您将业务逻辑从数据库中移到代码中,那么您就不会遇到这个问题 :-)
  • 有些东西,比如创建日期,最好放在数据库中
  • @Andrey:很多人会强烈反对你。也许这在 10 年前是可以接受的,但现在可以说所有业务逻辑都应该集中在代码中。
  • 我不认为这是生意,添加的日期是数据完整性。如果有业务添加日期,我会单独存储。

标签: c# sql linq-to-sql datetime default-constraint


【解决方案1】:

我建议您使用XML Editor 打开您的DBML 文件,并通过允许空值将该列的类型从DateTime 更改为DateTime?。保存它,将为您生成代码。

每当LINQ to SQL生成错误的DBML,最好自己编辑。

【讨论】:

  • dbml 生成错误的 xml,因为您设置错误。看我的回答
  • 感谢您的回复。但是将此值设置为 NULL 无效。正如 shaunmartin 和 Andrey 提到的那样,将“自动生成的值 = true”变成正确的事情。无论如何,谢谢你的帮助。 :)
【解决方案2】:

打开你的 dbml 并开启 对于自动生成的字段,“自动生成的值”= true。你应该很好地传递空值

【讨论】:

  • 感谢 Andrey。它传递了一个 NULL 值。但是由于该字段不是 NULL,因此会发生此错误。 “无法将值 NULL 插入 'UpdatedOn' 列,表 'myDataContext.tbl_CurrentProperty';列不允许空值。INSERT 失败。语句已终止。”
  • 这看起来像是一个设计问题。您的数据库应该恢复一个值以设置字段,自动生成该值(在这种情况下我的解决方案将起作用),或者允许该字段为空。您不应该使用诸如最小日期时间之类的东西来表示空值。如果您出于某种原因确实需要代码中的 sql 最小日期时间,您可以将其作为 System.Data.SqlTypes.SqlDateTime.MinValue()
  • @Kushan:这个答案是正确的。正如 shaunmartin 所指出的,如果与 decyclone 的答案结合使用,它将不起作用。您需要将列设置回不可为空并设置为DateTime(不是DateTime?),然后按照安德烈的建议设置Auto Generated = True
【解决方案3】:

Andrey'sanswer 部分正确。我刚刚对此进行了测试,这就是我发现的。

在您的 dbml 设计器中,在您的 UpdatedOn 列上设置以下内容:

Auto Generated Value = True 
Nullable = False

然后,在INSERT 上,如果您使用SQL Server Profiler 查看生成的SQL,您将看到UpdatedOn 不包含在INSERT 中。甚至没有空值。这很重要:要让 SQL Server 使用该列的默认值,INSERT 中的列必须省略。如果您在UpdatedOn 上设置Nullable = True,则LINQ to SQL 可能会在INSERT 上包含具有空值的列。

仅供参考,紧跟在INSERT 之后应该有一个SELECT,其中 LINQ to SQL 正在检索自动生成的值,因此您的实体对象具有最新值。

【讨论】:

    猜你喜欢
    • 2011-07-08
    • 1970-01-01
    • 1970-01-01
    • 2010-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-05
    • 2015-10-21
    相关资源
    最近更新 更多