【问题标题】:nhibernate : read write list of stringnhibernate:字符串的读写列表
【发布时间】:2014-12-18 12:53:10
【问题描述】:

我知道我可以使用 nhibernate 读取如下字符串的写入列表

HasMany(x => x.Attachments)
    .KeyColumn("RowId")
    .Table("PostTable").Element("PostKey");

但这会创建一个额外的表,有没有办法,例如UserType 或其他内容,以便我们可以直接写入列表...如果是,任何使用 nhibernate 的自定义 UserType 示例?带有示例代码...

我也希望如果我向列表添加值,也应该保存。我已经看到下面的示例代码在我们向列表中添加值时会中断......

   private virtual string StringValue
   public virtual IList<string> valueList
        { 
          get { return StringValue; }
          set { StringValue = string.Join(value, "|"); } 
         }

【问题讨论】:

  • 我的观点,根据我的经验......我不会走这条路。因为以后,如果您的应用程序成功,用户会要求您提供通过 Attachments... 的值进行搜索的功能...这将非常困难。我确实在任何地方都使用实体。 IE。 Attachment 带有 1) ID 和 2) 字符串描述... 3) 并引用回持有者。这样模型变得有点复杂(IList),但它可以用于搜索(子查询)。无论如何,如果你想使用IList&lt;string&gt; 分隔表仍然是最好的选择,我会说。
  • @RadimKöhler 我的问题纯粹是针对 List 的,与 List 无关...用户类型会不会更好??
  • 如果我有答案,我会给你。我的观点是,1) IList&lt;string&gt; 应该存储在单独的表中。该表将保存对根实体的引用(Holder_ID 列)和字符串值(值列)。 2)如果我们已经在那里,我建议走得更远。我会用自己的代理键扩展表并将其视为AttachmentFile 实体...但保持字符串列表内联...我没有看到任何优势...不确定这是否有帮助。 ..
  • 和用户类型......老实说,我从来没有使用过。即使尝试过。最后,我意识到 1) 纯实体 2) 多对一和 3) 一对多在任何情况下都足够了。它带来了很多好处,比如搜索......
  • 好的..太好了..感谢您的反馈:)

标签: c# nhibernate nhibernate-mapping-by-code usertype


【解决方案1】:

您可以像这样使用 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; }
    }
}

然后将 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();
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多