Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 如何使NHibernate持久化字符串。空属性值为NULL_.net_Nhibernate_Fluent Nhibernate - Fatal编程技术网

.net 如何使NHibernate持久化字符串。空属性值为NULL

.net 如何使NHibernate持久化字符串。空属性值为NULL,.net,nhibernate,fluent-nhibernate,.net,Nhibernate,Fluent Nhibernate,我有一个相当简单的类,我想通过NHibernate(w/Fluent映射)保存到SQL Server。该类主要由可选字符串字段组成 我的问题是我将类字段默认为string.empty以避免NullRefException,并且当NHibernate将行保存到数据库时,每列都包含一个空字符串而不是null 问题:当string属性为空字符串时,有没有办法让NHibernate自动保存null?或者我需要在代码中乱扔if(string.empty)检查吗?NHibernate正在执行您要求它执行的操

我有一个相当简单的类,我想通过NHibernate(w/Fluent映射)保存到SQL Server。该类主要由可选字符串字段组成

我的问题是我将类字段默认为string.empty以避免NullRefException,并且当NHibernate将行保存到数据库时,每列都包含一个空字符串而不是null


问题:当string属性为空字符串时,有没有办法让NHibernate自动保存null?或者我需要在代码中乱扔if(string.empty)检查吗?

NHibernate正在执行您要求它执行的操作。在一端,您说您试图避免
NullReferenceException
,在另一端,当值不为NULL时,您试图在数据库中保存
NULL
。在我看来,这似乎是一个矛盾。与其尝试解决此功能缺陷,不如尝试允许空值(并检查数据以防止NRE),或者不允许空值


如果你想用空字段和空字段覆盖一个特殊的情况,考虑读取正确的数据(不要输入到<代码>字符串。空< /COD>)。如果将空字符串视为该数据库中的空值,则只需将所有字段初始化为空字符串,以保持其简单性和一致性。

您可以使用用户类型执行此操作。我得出的结论是,空字符串在我的业务类中是无用的(这是一个令人头痛的问题),因此我将所有可空字符串数据库列转换为空字符串,反之亦然

流畅的用法是:

Map(x => x.MiddleName).CustomType(typeof(NullableString));

/// <summary>
/// UserType for string properties that are database nullable. Using this type
/// will substitue empty string for null when populating object properties
/// and null for empty string in database operations.
/// </summary>
/// <example>
/// Map(x => x.MiddleName).Length(30).Nullable().CustomType(typeof(NullableString));
/// </example>
public class NullableString : IUserType
{
    public new bool Equals(object x, object y)
    {
        if (ReferenceEquals(x, y))
        {
            return true;
        }
        if (x == null || y == null)
        {
            return false;
        }
        return x.Equals(y);
    }

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

    public object NullSafeGet(IDataReader rs, string[] names, object owner)
    {
        var valueToGet = NHibernateUtil.String.NullSafeGet(rs, names[0]);
        return valueToGet ?? string.Empty;
    }

    public void NullSafeSet(IDbCommand cmd, object value, int index)
    {
        var stringObject = value as string;
        object valueToSet = string.IsNullOrEmpty(stringObject) ? null : stringObject;
        NHibernateUtil.String.NullSafeSet(cmd, valueToSet, index);
    }

    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 DeepCopy(cached);
    }

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

    public SqlType[] SqlTypes
    {
        get
        {
            return new[] { new SqlType(DbType.String)};
        }
    }

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

    public bool IsMutable
    {
        get { return false; }
    }
}
Map(x=>x.MiddleName).CustomType(typeof(NullableString));
/// 
///数据库可为空的字符串属性的用户类型。使用此类型
///填充对象属性时将空字符串替换为null
///数据库操作中的空字符串为空。
/// 
/// 
///Map(x=>x.MiddleName).Length(30).Nullable().CustomType(typeof(NullableString));
/// 
公共类NullableString:IUserType
{
公共新布尔等于(对象x、对象y)
{
if(ReferenceEquals(x,y))
{
返回true;
}
如果(x==null | | y==null)
{
返回false;
}
返回x等于(y);
}
公共int GetHashCode(对象x)
{
返回x.GetHashCode();
}
公共对象NullSafeGet(IDataReader rs,字符串[]名称,对象所有者)
{
var valueToGet=NHibernateUtil.String.NullSafeGet(rs,name[0]);
返回值设置??字符串。为空;
}
public void NullSafeSet(IDbCommand cmd,对象值,int索引)
{
var stringObject=作为字符串的值;
object valueToSet=string.IsNullOrEmpty(stringObject)?null:stringObject;
NHibernateUtil.String.NullSafeSet(cmd,valueToSet,index);
}
公共对象深度复制(对象值)
{
返回值;
}
公共对象替换(对象原始、对象目标、对象所有者)
{
归还原件;
}
公共对象集合(对象缓存,对象所有者)
{
返回DeepCopy(缓存);
}
公共对象(对象值)
{
返回DeepCopy(值);
}
公共SqlType[]SqlTypes
{
得到
{
返回new[]{newsqltype(DbType.String)};
}
}
公共类型返回类型
{
获取{return typeof(string);}
}
公共布尔可换
{
获取{return false;}
}
}

我不会说你需要在代码中乱扔支票。我使用单一扩展方法:

public static class StringExtensions
{
    public static string NullIfEmpty(this string s)
    {
        return string.IsNullOrEmpty(s) ? null : s;
    }
}
然后按以下方式编写实体类:

public class MyEntity
{
    private string name;

    public string Name
    {
        get { return name; }
        set { name = value.NullIfEmpty(); }
    }
}
我认为最好明确指出您想要这种行为,因为在许多情况下,空字符串可能是数据库中的有效值


使用自定义类型也有效;然而,我总觉得这种“取消”行为应该是实体的行为,而不是映射器的行为,实体本身应该有一个契约,上面写着“我忽略空字符串。”

是的。。。这正是我要求它做的。。。仍然希望找到一种简单的方法,允许代码将null视为与string.empty相同的值,但让数据库将它们视为不相等的值。“功能缺陷”?我肯定会在我的词汇表中添加这个短语。:-)我认为这是o/r不匹配的一部分,因此映射者有责任处理它。我还没有为业务对象中的空字符串提供有效的用例,或者需要区分数据库中的空字符串和空字符串。如果您使用的是Oracle,它会将长度为零的字符串存储为null。@Jamie:我想在Oracle中是这样的;至少在SQL Server中,零长度字符串不同于
NULL
,因此它实际上与.NET字符串完全匹配,而不是不匹配。长度为零的字符串在语义上也不同于
NULL
-
NULL
表示未知或未定义,而长度为零的字符串表示值已定义,但仅为空。类型完全匹配,但我正在解决对象的o/r不匹配问题。我知道null的意思,我要说的是字符串的区别实际上是零。标准情况是,我正在从用户输入设置一个属性,因此我读取控件的Text属性,该属性返回空字符串,即使用户没有触摸该控件。为了知道用户的意思是“undefined/unknown/null”,我必须提供一个额外的UI元素来切换文本控件。@Jamie:我没有说它必须是UI逻辑的一部分-这就是为什么我在上面发布了扩展方法和示例,模型负责此转换。我真的不明白所谓的对象关系阻抗失配在这里是如何应用的。这不是一个对象/关系映射问题,而是一个域/用户界面映射问题。用户界面逻辑就是一个例子,说明为什么空字符串很少(在我的经验中几乎从来没有)在