具有默认值

时间:2016-03-22 07:38:11

标签: c# sql-server nhibernate fluent-nhibernate fluent-nhibernate-mapping

我知道有很多线索,我已经阅读了大部分内容。但对我来说有些事情仍然不清楚仍然无效。

如果我的数据库模式上有一个DateTime类型的字段,我想为它分配一个默认值,我会这样做:

create table [mySchema].[MyTable](
    ObjectGuid uniqueidentifier CONSTRAINT Id PRIMARY KEY,
    SomeTextToStore nvarchar(128) NULL,
    CDate datetime NOT NULL DEFAULT GETDATE(),
    CUser nvarchar(64) DEFAULT CURRENT_USER
);
GO

(不知道它是否重要:我正在使用SQL Server Express 2014 .Fluent配置适用于SQL Server 2012.)

从ISQL执行INSERT时,这样可以正常工作,插入添加记录时的时间戳。

使用流利的我会写这样的东西:

域:

public class MyObject
{
    public virtual Guid Id {get; set}
    public virtual string SomeTextToStore {get; set;}
    public virtual DateTime? CDate {get; set;}
    public virtual string CUser {get; set;}
}

注意:我让CDate可以为空!

这样的映射类:

class MyObjectMap : ClassMap<MyObject>
{
    public MyObjectMap()
    {
        Table("MySchema.MyTable");
        Id(x => x.Id).GeneratedBy.GuidComb();
        Map(x => x.SomeTextToStore).Length(128).Nullable();
        Map(x => x.CDate).Not.Nullable().Default("getdate()");
        Map(x => x.CUser).Not.Nullable().Default("CURRENT_USER);
    }
}

在程序中(在我的例子中,这是一个可以从几种类型的程序调用的库)我做了类似的事情:

public void EnterSomeText()
{
    using (var session = sessionManager.OpenSession())
    {
        using (var transaction = session.BeginTransaction())
        {
            var myObj = new MyObject();
            myObj.SomeTextToStore("bla bla bla");
            session.SaveOrUpdate(myObj);
            transaction.Commit();
        }
        session.Close();
    }
}

这始终以 DateTime溢出异常结束! (SqlDateTime溢出。必须在1/1/1753 12:00:00 AM和12/31/9999 11:59:59 PM之间)

看起来没有将值传递给文件CDate导致问题。当我在我的库中添加默认值时,它可以工作:

...
myObj.SomeTextToStore("bla bla bla");
myObj.CDate = DateTime.Now;   // <---- Set the date here
session.SaveOrUpdate(myObj);
...

但这不是解决方案......

问题:

  1. 我做错了什么/缺少什么?
  2. 什么是正确的策略 定义默认值?在数据库上或仅在代码中执行此操作? (什么时候 开始一个简单的新香草项目,我宁愿做 来自C#代码的所有内容,甚至可以创建并稍后更新架构......)
  3. 关于域类:创建构造函数是否明智, 用默认值填充字段?
  4. 我为字段CUser执行此操作,因为在CUser我想添加当前用户上下文

    public MyObject()
    {
       var o = System.Security.Principal.WindowsIdentity.GetCurrent();
       if (o != null)
       {
           CUser = o.Name;
       }  
    }
    

    我没有在我的数据库访问层库中填入当前日期的CDate字段,而是在域类的构造函数中也可以这样做:

    public MyObject()
    {
       var o = System.Security.Principal.WindowsIdentity.GetCurrent();
       if (o != null)
       {
           CUser = o.Name;
       } 
       CDate = DateTime.Now; 
    }
    

    非常感谢您的帮助和评论!

2 个答案:

答案 0 :(得分:3)

通常对于这种类型的映射,我在映射中执行以下操作:

DynamicInsert();
DynamicUpdate();

这种方式如果你在C#中有可空类型并且你没有将它们设置为任何东西,那么nhibernate将不会在insert或update语句中包含它们。当nhibernate正在更新代码中未更改的列时,我从不喜欢它。

此外,当您在映射中指定.Not.Nullable();.Default("getdate()")时,所有这些都用于模式生成。它实际上并不是由nhibernate用来进行任何验证或默认。这取决于数据库。

答案 1 :(得分:1)

您已在数据库中将此列定义为NOT NULL,并在映射中将其定义为Nullable()。 FluentNHibernate正在向数据库发送DbNull,因为数据库列不可为空而被拒绝。

您应该决定逻辑所在的位置。这是您的代码还是主数据库?

例如,在this question中讨论了在FlientNHibernate中设置默认值。

建议的代码是:

Map(x => x.SubmitionDate).Default("getdate()").Not.Nullable();

一般情况下,我总是建议使用NHibernate Profiler(付费工具)来查看哪些查询进入数据库以及它们失败的原因。非常有利于优化,您正在使用ORM,现在要小心!