代码之家  ›  专栏  ›  技术社区  ›  Xaisoft

未将日期属性设置为对象将导致错误

  •  4
  • Xaisoft  · 技术社区  · 14 年前

    我有一张桌子 smalldatetime NOT NULL 默认值为的字段 getdate() . 在表中创建新记录时,我不会设置 smalldatetime 字段在代码中通过LINQ To SQL语法,我只是让数据库设置默认值,即当前日期。如果我没有在代码中显式设置它,它将引发以下错误:

    SqlDateTime溢出。必须介于1/1/1753 12:00:00 AM和12/31/9999 11:59:59 PM之间。

    如果我要在数据库中设置默认值,为什么要在代码中设置它?我注意到,在LINQ to SQL方面,日期有一些古怪的东西。

    4 回复  |  直到 14 年前
        1
  •  3
  •   bdukes Jon Skeet    14 年前

    而不是将字段设置为 IsDbGenerated ,您可以考虑设置 AutoSync 价值 OnInsert . ISDBG生成 不会让您设置字段的值(这可能是您想要的“创建日期”字段的值,但不是“上次修改”字段的值)。

    但是,如果您使用的是ORM,我会要求您考虑是否在数据库和应用程序代码中都需要应用程序逻辑。在代码中实现默认值(通过 partial methods 喜欢 Insert[Entity] )?

        2
  •  1
  •   John Gietzen    14 年前

    您必须设置generated属性,这样LINQ to SQL就不会在创建时发送其默认值。

    该属性在实体上称为“自动生成的值”。

    alt text

        3
  •  0
  •   p.campbell    14 年前

    要解决这个问题,请确保LINQ-To-SQL模型知道 smalldatetime 字段由数据库自动生成。

    在LINQ To SQL图中选择表的字段,并找到Properties窗口。调整 自动生成值 属性到 真的 . 这将确保字段不包含在 INSERT 由LINQ To SQL生成的语句。

    alt text

    或者,您必须自己指定:

    if (newCustomer.DateTimeCreated == null) {
           newCustomer.DateTimeCreated = DateTime.Now; // or UtcNow 
     }
    
        4
  •  0
  •   D'Arcy Rittich    14 年前

    LINQ To SQL不会以一种随后可以更新值的方式观察数据库默认值。为了允许这样做,您需要在代码中设置默认值。

    当创建新对象时 NOT NULL 对于数据库默认值,C#将使用默认值,例如 MinValue 对于数字和日期、空guid(零)等,可以查找这些条件并替换为自己的默认值。

    这是LINQ To SQL的已知设计问题。有关详细讨论,请参见以下链接:

    http://www.codeproject.com/KB/linq/SettingDefaultValues.aspx

    在应用程序中设置默认值的一些示例代码:

    private void SetDefaults(object LinqObj)
    {
        // get the properties of the LINQ Object
        PropertyInfo[] props = LinqObj.GetType().GetProperties();
    
        // iterate through each property of the class
        foreach (PropertyInfo prop in props)
        {
            // attempt to discover any metadata relating to underlying data columns
            try
            {
                // get any column attributes created by the Linq designer
                object[] customAttributes = prop.GetCustomAttributes
                (typeof(System.Data.Linq.Mapping.ColumnAttribute), false);
    
                // if the property has an attribute letting us know that 
                // the underlying column data cannot be null
                if (((System.Data.Linq.Mapping.ColumnAttribute)
                (customAttributes[0])).DbType.ToLower().IndexOf("not null") != -1)
                {
                    // if the current property is null or Linq has set a date time 
                // to its default '01/01/0001 00:00:00'
                    if (prop.GetValue(LinqObj, null) == null || prop.GetValue(LinqObj, 
                    null).ToString() == (new DateTime(1, 1, 1, 0, 0, 0)).ToString())
                    {
    
                        // set the default values here : could re-query the database, 
                        // but would be expensive so just use defaults coded here
                        switch (prop.PropertyType.ToString())
                        {
                            // System.String / NVarchar
                            case "System.String":
                                prop.SetValue(LinqObj, String.Empty, null);
                                break;
                            case "System.Int32":
                            case "System.Int64":
                            case "System.Int16":
                                prop.SetValue(LinqObj, 0, null);
                                break;
                            case "System.DateTime":
                                prop.SetValue(LinqObj, DateTime.Now, null);
                                break;
                        }
                    }
                }
            }
            catch
            {
                // could do something here ...
            }
        }