簡體   English   中英

使NHibernate使用System.Guid.Empty值“轉換” C#POCO Guid屬性以將其作為Database uniqueidentifier字段保存為NULL?

[英]Making NHibernate “translate” C# POCO Guid property with value of System.Guid.Empty to be saved as NULL for the Database uniqueidentifier field?

我們的辦公室團隊正在研究使用.NET Framework 4和NHibernate 3.3.1的ASP.NET項目。

我有一個名為AllResourcesInfo的POCO域類(該類最終映射到數據庫中的Resource表,該數據庫內部連接到其他一些表,但是為了簡單起見,我們只說AllResourcesInfo映射到Resource表)。

我也有一個稱為Department的POCO域類(該類最終映射到數據庫中的Department表)

AllResourcesInfo可能與部門有多對一關系。

如果AllResourcesInfo的實例屬於部門,則AllResourcesInfo.DepartmentDatabaseID具有在Department實體中的有效DepartmentDatabaseID。

但是,如果AllResourcesInfo的實例不屬於某個部門,則AllResourcesInfo.DepartmentDatabaseID在數據庫中的值為NULL。 數據庫。

當我使用NHibernate從AllResourcesInfo表中檢索(基本上是NHibernate對數據庫進行讀取)值時,NHibernate將使用00000000-0000-0000-0000-0000-000000000000值(即System.Guid)填充AllResourcesInfo.DepartmentDatabaseID的C#POCO屬性。 .Empty值)如果AllResourcesInfo不屬於部門

但是,當我使用NHibernate Session保存不屬於任何部門的全新的AllResourcesInfo的C#POCO實例時,我用00000000-0000-0000-0000-0000-000000000000的值(即系統)填充AllResourcesInfo.DepartmentDatabaseID的POCO屬性。 .Guid.Empty值),但數據庫顯然會引發錯誤,因為在數據庫的Department表中顯然不存在Guid值00000000-0000-0000-0000-000000000000。

總而言之,當我們希望NHibernate Session Save將uniqueidentifier字段值保留為null時,它無法將數據庫中的uniqueidentifier字段保存(或保留為NULL)。

有人可以告訴我如何確保NHibernate“轉換”具有System.Guid.Empty值的C#POCO Guid屬性,以便將數據庫uniqueidentifier字段值保存(或保留為NULL)嗎?

Guid不能為null。 您可以將類型更改為Nullable<Guid>Guid? 簡而言之,允許為空。

您需要實現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" />

您要做的是在數據庫中的Guid(不可為空的Guid)和GUID之間創建映射。 這是NHibernate中IUserType接口的目的。 您將需要一個自定義的GuidUserType類來執行翻譯,然后在映射定義中引用它(hbxml,fluent等)。 有關完整說明,請參見http://blog.miraclespain.com/archive/2008/Mar-18.html

在Department對象的主鍵的映射中,應該有一個名為unsaved-value的屬性。 將其設置為Guid.Empty的值,一切都會好的。

以下是使用原始hbm映射的示例:

<id name="DepartmentId" type="Guid" unsaved-value="00000000-0000-0000-0000-000000000000">
    <generator class="guid" />
</id>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM