具有默认值的 DateTime 的 Fluent NHibernate 映射
Fluent NHibernate mapping for DateTime with default value
我知道有很多关于这个的帖子,我已经阅读了其中的大部分。然而对我来说 有几件事仍然不清楚 并且仍然不起作用。
如果我的数据库架构中有一个 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:
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);
...
但这并不是真正的解决方案....
问题:
- 我做错了什么/遗漏了什么?
- 正确的策略是什么时候
定义默认值?是在数据库上还是在代码中? (什么时候
开始一个普通的新香草项目,我更愿意做
C# 代码中的所有内容,甚至创建和稍后更新架构...)
- 关于 域 classes: 创建构造函数是否明智,
用默认值填充字段?
我为字段 CUser
执行此操作,因为在 CUser
中我想添加当前用户上下文
public MyObject()
{
var o = System.Security.Principal.WindowsIdentity.GetCurrent();
if (o != null)
{
CUser = o.Name;
}
}
除了在我的数据库访问层库中用当前日期填充 CDate 字段外,我还可以在域的构造函数中这样做-class 像这样:
public MyObject()
{
var o = System.Security.Principal.WindowsIdentity.GetCurrent();
if (o != null)
{
CUser = o.Name;
}
CDate = DateTime.Now;
}
非常感谢您的帮助和意见!
您已将此列定义为数据库中的 NOT NULL
和映射中的 Nullable()
。 FluentNHibernate 正在向数据库发送 DbNull
,但该数据库被拒绝,因为数据库列不可为空。
您应该决定您的逻辑所在的位置。这是你的代码还是数据库谁做主?
在 FlientNHibernate 中设置默认值已讨论,例如,在 this question。
那里的建议代码是:
Map(x => x.SubmitionDate).Default("getdate()").Not.Nullable();
一般来说,我总是建议使用 NHibernate Profiler(付费工具)来查看哪些查询进入了数据库以及它们失败的原因。对优化非常宝贵,你正在使用ORM,现在要小心!
通常对于这种类型的映射,我会在我的映射中执行以下操作:
DynamicInsert();
DynamicUpdate();
这样,如果您在 C# 中有可空类型并且您没有将它们设置为任何内容,nhibernate 将不会将它们包含在插入或更新语句中。当 nhibernate 更新代码中未更改的列时,我从来都不喜欢它。
此外,当您在映射中指定 .Not.Nullable();
和 .Default("getdate()")
时,所有这些都用于模式生成。 nhibernate 实际上并没有使用它来进行任何验证或默认设置。这留给了数据库。
我知道有很多关于这个的帖子,我已经阅读了其中的大部分。然而对我来说 有几件事仍然不清楚 并且仍然不起作用。
如果我的数据库架构中有一个 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:
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);
...
但这并不是真正的解决方案....
问题:
- 我做错了什么/遗漏了什么?
- 正确的策略是什么时候 定义默认值?是在数据库上还是在代码中? (什么时候 开始一个普通的新香草项目,我更愿意做 C# 代码中的所有内容,甚至创建和稍后更新架构...)
- 关于 域 classes: 创建构造函数是否明智, 用默认值填充字段?
我为字段 CUser
执行此操作,因为在 CUser
中我想添加当前用户上下文
public MyObject()
{
var o = System.Security.Principal.WindowsIdentity.GetCurrent();
if (o != null)
{
CUser = o.Name;
}
}
除了在我的数据库访问层库中用当前日期填充 CDate 字段外,我还可以在域的构造函数中这样做-class 像这样:
public MyObject()
{
var o = System.Security.Principal.WindowsIdentity.GetCurrent();
if (o != null)
{
CUser = o.Name;
}
CDate = DateTime.Now;
}
非常感谢您的帮助和意见!
您已将此列定义为数据库中的 NOT NULL
和映射中的 Nullable()
。 FluentNHibernate 正在向数据库发送 DbNull
,但该数据库被拒绝,因为数据库列不可为空。
您应该决定您的逻辑所在的位置。这是你的代码还是数据库谁做主?
在 FlientNHibernate 中设置默认值已讨论,例如,在 this question。
那里的建议代码是:
Map(x => x.SubmitionDate).Default("getdate()").Not.Nullable();
一般来说,我总是建议使用 NHibernate Profiler(付费工具)来查看哪些查询进入了数据库以及它们失败的原因。对优化非常宝贵,你正在使用ORM,现在要小心!
通常对于这种类型的映射,我会在我的映射中执行以下操作:
DynamicInsert();
DynamicUpdate();
这样,如果您在 C# 中有可空类型并且您没有将它们设置为任何内容,nhibernate 将不会将它们包含在插入或更新语句中。当 nhibernate 更新代码中未更改的列时,我从来都不喜欢它。
此外,当您在映射中指定 .Not.Nullable();
和 .Default("getdate()")
时,所有这些都用于模式生成。 nhibernate 实际上并没有使用它来进行任何验证或默认设置。这留给了数据库。