2

私たちのオフィスチームは、.NETFramework4とNHibernate3.3.1を使用するASP.NETプロジェクトに取り組んでいます。

AllResourcesInfoというPOCOドメインクラスがあります(これは、最終的には他のテーブルに内部結合されているデータベース内のResourceテーブルにマップされますが、簡単にするために、AllResourcesInfoはResourceテーブルにマップされるとしましょう)。

また、DepartmentというPOCOドメインクラスがあります(これは最終的にデータベースのDepartmentテーブルにマップされます)。

AllResourcesInfoは、部門と多対1の関係を持つ可能性があります。

AllResourcesInfoのインスタンスが部門に属している場合、AllResourcesInfo.DepartmentDatabaseIDには、Departmentエンティティにある有効なDepartmentDatabaseIDがあります。

ただし、AllResourcesInfoのインスタンスが部門に属していない場合、AllResourcesInfo.DepartmentDatabaseIDのデータベースの値はNULLになります。データベース。

NHibernateを使用してAllResourcesInfoテーブルから値を取得する(基本的にNHibernateはデータベースの読み取りを行う)と、NHibernateはAllResourcesInfo.DepartmentDatabaseIDのC#POCOプロパティに00000000-0000-0000-0000-000000000000値(つまり、System.Guid)を入力します。 .Empty value)AllResourcesInfoが部門に属していない場合

ただし、NHibernate Sessionを使用して、どの部門にも属していないAllResourcesInfoの新しいC#POCOインスタンスを保存する場合、AllResourcesInfo.DepartmentDatabaseIDのPOCOプロパティに00000000-0000-0000-0000-000000000000値(つまり、システム)を入力します。 .Guid.Empty value)しかし、00000000-0000-0000-0000-000000000000のGUID値がデータベースのDepartmentテーブルに存在しないため、データベースは明らかにエラーをスローします。

要約すると、NHibernate Session Saveは、uniqueidentifierフィールドの値をnullのままにしたい場合、データベース内のuniqueidentifierフィールドをNULLの値で保存(または残す)できません。

NHibernateがSystem.Guid.Emptyの値を持つC#POCO Guidプロパティをデータベースのuniqueidentifierフィールド値に対してNULLとして保存(または残)することを保証する方法を教えてください。

4

4 に答える 4

3

GUIDをnullにすることはできません。タイプをNullable<Guid>、またはGuid?略してnullを許可するように変更できます。

于 2013-02-01T20:27:45.637 に答える
3

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" />
于 2013-02-01T22:34:39.947 に答える
2

実行したいのは、Guid(null許容のGuidではない)とデータベース内のGUIDの間のマッピングを作成することです。これがNHibernateのIUserTypeインターフェースの目的です。変換を実行し、マッピング定義(hbxml、fluentなど)でそれを参照するカスタムGuidUserTypeクラスが必要になります。詳細な説明については、 http://blog.miraclespain.com/archive/2008/Mar-18.htmlを参照してください。

于 2013-02-01T21:28:23.270 に答える
0

Departmentオブジェクトの主キーのマッピングには、unsaved-valueというプロパティが必要です。これをGuid.Emptyの値に設定すると、すべて問題ありません。

以下は、生のhbmマッピングを使用してそれを行う方法の例です。

<id name="DepartmentId" type="Guid" unsaved-value="00000000-0000-0000-0000-000000000000">
    <generator class="guid" />
</id>
于 2013-02-05T22:36:02.553 に答える