【问题标题】:Mapping collection of strings with NHibernate使用 NHibernate 映射字符串集合
【发布时间】:2010-10-11 00:48:24
【问题描述】:

我有一个带有属性IList<string> 的域类,我想将它映射到具有单个数据值的表(即它有一个ID、域实体表的外键ID 和一个varchar 数据列) .

我不断收到错误:

关联引用未映射的类:System.String

如何将表映射到字符串集合?

【问题讨论】:

  • 这并没有错。您只是使用一对多映射它,这仅适用于实体列表。看看 derek 和 Frederiks 的回答。

标签: .net nhibernate


【解决方案1】:

我刚刚遇到了类似的情况;我发现确实可以映射字符串集合。 请注意,您必须将这些字符串映射为值对象。

这就是我所拥有的:

public class Chapter
{
    private ISet<string> _synonyms = new HashedSet<string>();

    public ReadOnlyCollection<string> Synonyms
    {
       get { return new List<string>(_synonyms).AsReadOnly(); }
    }
}

映射:

<class name="Chapter" table="Chapter">
   <set name="Synonyms" table="ChapterSynonyms">
       <key column="ChapterId" />
       <element column="ChapterCode" type="string" />
   </set>
</class>

【讨论】:

  • 最近又遇到了这个问题,这是我根据你的 XML 映射使用的 FluentNHibernate 映射:mapping.HasMany(x => x.Synonyms).AsBag().Element("ChapterCode", m => m.Type());
  • HashedSet 不应该是 HashShet 吗?
  • @roryf 你正在使用一个包,它应该是一个集合。正确的代码应该是: HasMany(x => x.Synonyms).Table("Synonyms").AsSet().Element("ChapterCode", m => m.Type().Not.Nullable() );
  • No HashedSet 不应该是 HashSet。 HashedSet 是一个 Iesi.Collections 类型,这在 MS 创建 HashSet 类型之前使用 NHibernate 时使用。虽然示例代码也适用于 MS HashSet,但使用 HashedSet 是完全有效的。
【解决方案2】:

除非我弄错了,否则你可以这样做:

<bag name="Identities" access="property">
  <key column="accountId"/>
  <element column="identity" type="string"/>
</bag>

身份为IList&lt;string&gt;

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 2017-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多