C# nhibernate:字符串的读写列表

C# nhibernate:字符串的读写列表,c#,nhibernate,mapping-by-code,usertype,C#,Nhibernate,Mapping By Code,Usertype,我知道我可以用nhibernate读写下面的字符串列表 HasMany(x => x.Attachments) .KeyColumn("RowId") .Table("PostTable").Element("PostKey"); 但这会创建一个额外的表,是否有一种方法,例如,或其他方法,以便我们可以直接写入列表。。。如果是,使用nhibernate的任何自定义用户类型示例??使用示例代码 我还想知道,若我给列表添加了值,那个么它也应该被保存。我看到了下面的示例代码,如果

我知道我可以用nhibernate读写下面的字符串列表

HasMany(x => x.Attachments)
    .KeyColumn("RowId")
    .Table("PostTable").Element("PostKey");
但这会创建一个额外的表,是否有一种方法,例如,或其他方法,以便我们可以直接写入列表。。。如果是,使用nhibernate的任何自定义用户类型示例??使用示例代码

我还想知道,若我给列表添加了值,那个么它也应该被保存。我看到了下面的示例代码,如果我们向列表中添加值,代码会中断

   private virtual string StringValue
   public virtual IList<string> valueList
        { 
          get { return StringValue; }
          set { StringValue = string.Join(value, "|"); } 
         }
私有虚拟字符串字符串值
公共虚拟IList价值表
{ 
获取{return StringValue;}
设置{StringValue=string.Join(值“|”);}
}

您可以使用IUserType这样做:

public class DelimitedList : IUserType
{
    private const string delimiter = "|";

    public new bool Equals(object x, object y)
    {
        return object.Equals(x, y);
    }

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

    public object NullSafeGet(IDataReader rs, string[] names, object owner)
    {
        var r = rs[names[0]];
        return r == DBNull.Value 
            ? new List<string>()
            : ((string)r).SplitAndTrim(new [] { delimiter });
    }

    public void NullSafeSet(IDbCommand cmd, object value, int index)
    {
        object paramVal = DBNull.Value;
        if (value != null)
        {
            paramVal = ((IEnumerable<string>)value).Join(delimiter);
        }
        var parameter = (IDataParameter)cmd.Parameters[index];
        parameter.Value = paramVal;
    }

    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 SqlType[] SqlTypes
    {
        get { return new SqlType[] { new StringSqlType() }; }
    }

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

    public bool IsMutable
    {
        get { return false; }
    }
}
公共类分隔符列表:IUserType
{
私有常量字符串分隔符=“|”;
公共新布尔等于(对象x、对象y)
{
返回对象。等于(x,y);
}
公共int GetHashCode(对象x)
{
返回x.GetHashCode();
}
公共对象NullSafeGet(IDataReader rs,字符串[]名称,对象所有者)
{
var r=rs[名称[0]];
返回r==DBNull.Value
?新名单()
:((字符串)r).SplitAndTrim(新[]{delimiter});
}
public void NullSafeSet(IDbCommand cmd,对象值,int索引)
{
对象paramVal=DBNull.Value;
if(值!=null)
{
paramVal=((IEnumerable)值).Join(分隔符);
}
var参数=(IDataParameter)命令参数[索引];
parameter.Value=paramVal;
}
公共对象深度复制(对象值)
{
返回值;
}
公共对象替换(对象原始、对象目标、对象所有者)
{
归还原件;
}
公共对象集合(对象缓存,对象所有者)
{
返回缓存;
}
公共对象(对象值)
{
返回值;
}
公共SqlType[]SqlTypes
{
获取{return new SqlType[]{new StringSqlType()};}
}
公共类型返回类型
{
获取{return typeof(IList);}
}
公共布尔可换
{
获取{return false;}
}
}
然后将IList属性定义为type=“MyApp.DelimitedList,MyApp”

注意:SplitAndTrim是一个字符串扩展,具有我创建的各种覆盖。以下是核心方法:

public static IList<string> SplitAndTrim(this string s, StringSplitOptions options, params string[] delimiters)
    {
        if (s == null)
        {
            return null;
        }
        var query = s.Split(delimiters, StringSplitOptions.None).Select(x => x.Trim());
        if (options == StringSplitOptions.RemoveEmptyEntries)
        {
            query = query.Where(x => x.Trim() != string.Empty);
        }
        return query.ToList();
    }
公共静态IList SplitAndTrim(此字符串为s,StringSplitOptions选项,参数字符串为[]分隔符)
{
如果(s==null)
{
返回null;
}
var query=s.Split(分隔符,StringSplitOptions.None);
如果(选项==StringSplitOptions.RemoveEmptyEntries)
{
query=query.Where(x=>x.Trim()!=string.Empty);
}
返回query.ToList();
}

根据我的经验,我的观点。。。我不会走这条路。因为稍后,如果您的应用程序成功,用户将要求您提供通过
附件中的值进行搜索的功能。。。这将是非常困难的。我在任何地方都使用实体。即带有1)ID和2)字符串描述的
附件
。。。3) 并引用回持有者。这样模型就变得有点复杂(IList),但它可以用于搜索(子查询)。无论如何,如果您想使用IList
分隔表仍然是最好的选择,我会说。@RadimKöhler我的问题纯粹是为了列表,与列表无关。。。用户类型会更好吗?如果我有答案,我会给你的。我的观点是,1)
IList
应该存储在单独的表中。该表将保存对根实体(Holder_ID列)和字符串值(value列)的引用。2) 如果我们已经做到了,我建议再进一步。我将使用它自己的代理键扩展表,并将其视为
附件
文件
实体。。。但是保持字符串列表的内联。。。我看不出有什么好处。。。不确定这是否有帮助…和用户类型。。。老实说,我从来没用过。即使尝试过。最后,我重申1)纯实体2)多对一和3)一对多在任何场景中都足够了。它带来了很多好处,比如搜索……好吧。。伟大的感谢您的反馈:)