c# - 将值为 System.Guid.Empty 的 NHibernate "translate"C# POCO Guid 属性保存为数据库 uniqueidentifier 字段的 NULL?

标签 c# nhibernate session guid hbmxml

我们的办公室团队正在开展使用 .NET Framework 4 和 NHibernate 3.3.1 的 ASP.NET 项目

我有一个名为 AllResourcesInfo 的 POCO 域类(它最终映射到数据库中的资源表,该表内部连接到其他一些表,但为了简单起见,我们只说 AllResourcesInfo 映射到资源表) .

我还有一个名为 Department 的 POCO 域类(它最终映射到数据库中的 Department 表)

AllResourcesInfo 可能与部门具有多对一关系。

如果 AllResourcesInfo 的实例属于部门,则 AllResourcesInfo.DepartmentDatabaseID 具有部门实体中的有效 DepartmentDatabaseID。

但是,如果 AllResourcesInfo 的实例不属于部门,则 AllResourcesInfo.DepartmentDatabaseID 在数据库中具有 NULL 值。数据库。

当我使用 NHibernate 从 AllResourcesInfo 表中检索(基本上 NHibernate 读取数据库)值时,NHibernate 将使用 00000000-0000-0000-0000-000000000000 值(即System.Guid.Empty value ) 如果 AllResourcesInfo 不属于部门

但是,当我使用 NHibernate Session 保存一个全新的 C# POCO AllResourcesInfo 实例时,它不属于任何部门,我用 00000000-0000-0000-0000-000000000000 值填充 AllResourcesInfo.DepartmentDatabaseID 的 POCO 属性(即 System.Guid.Empty 值)但是数据库显然会抛出错误,因为数据库的 Department 表中显然不存在 00000000-0000-0000-0000-000000000000 的 Guid 值。

总而言之,当我们希望 NHibernate Session Save 将 uniqueidentifier 字段值保留为 null 时,NHibernate Session Save 无法在数据库中保存(或保留)值为 NULL 的 uniqueidentifier 字段。

有人能告诉我我们如何确保 NHibernate“翻译”一个值为 System.Guid.Empty 的 C# POCO Guid 属性,以便将其保存(或保留)为数据库唯一标识符字段值的 NULL?

最佳答案

您需要实现 NHibernate 的 IUserType。

它应该是这样的:

using NHibernate.SqlTypes;
using NHibernate.UserTypes;

[Serializable] //to allow NH configuration serialization
public class GuidTypeConverter : IUserType
{
    SqlType[] sqlTypes;

    public GuidTypeConverter()
    {
        sqlTypes = new[] { SqlTypeFactory.GetSqlType(DbType.Guid, 0, 0) };
    }

    public SqlType[] SqlTypes
    {
        get { return sqlTypes; }
    }

    public Type ReturnedType
    {
        get { return typeof(Guid); }
    }

    public object NullSafeGet(IDataReader rs, string[] names, object owner)
    {
        if (rs[names[0]] == DBNull.Value)
        {
            return Guid.Empty;
        }

        return (Guid) rs[names[0]];
    }

    public void NullSafeSet(IDbCommand cmd, object value, int index)
    {
        var param = (IDataParameter) cmd.Parameters[index];
        param.DbType = sqlTypes[0].DbType;
        var guid = (Guid) value;

        if (guid != Guid.Empty)
        {
            param.Value = guid;    
        }
        else
        {
            param.Value = DBNull.Value;
        }
    }

    public bool IsMutable
    {
        //guid is struct so it's not mutable
        get { return false; }
    }

    public object DeepCopy(object value)
    {
        return value;
    }

    public object Replace(object original, object target, object owner)
    {
        return original;
    }

    public object Assemble(object cached, object owner)
    {
        return cached;
    }

    public object Disassemble(object value)
    {
        return value;
    }

    public new bool Equals(object x, object y)
    {
        return x != null && x.Equals(y); 
    }

    public int GetHashCode(object x)
    {
        return x.GetHashCode();
    }
}

(请注意,我还没有测试过,这里有转换 - 可能需要进行一些调整)

在您指定的映射中:

<property name="GuidProperty" column="guidColumn"   type="GuidTypeConverterNamespace.GuidTypeConverter, GuidTypeConverterAssemblyName" />

关于c# - 将值为 System.Guid.Empty 的 NHibernate "translate"C# POCO Guid 属性保存为数据库 uniqueidentifier 字段的 NULL?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14654364/

相关文章:

c# - 如何在构造后修改值类型中的只读字段

c# - Linq to NHibernate 返回名称以字符串列表内容开头的实体

c# - 在属性中声明变量是否被认为是不好的做法?

c# - 如果达到最大连接数/ session 数,则 asp.net 重定向

ios - Multipeer Connectivity 终止 session

c# - 如何快速对齐 WPF 窗口中的控件?

c# - 如何在编译后更改 AssemblyName 以在 Unity3d 中作为 mod 加载

c# - 请提供引用/指导以在 Asp.Net MVC(C#) 中制作用于管理邮件(如 Microsoft Outlook)的 Web 应用程序

.NET 4.0 解决方案中的 NHibernate 1.2

"__php_incomplete_class"的 PHP 问题