2009-03-03 4 views
13

У меня есть класс домена с свойством IList<string>, который я хочу сопоставить с таблицей с одним значением данных (то есть у нее есть идентификатор, идентификатор внешнего ключа для таблицы сущности домена и varchar).Сопоставление коллекции строк с NHibernate

Я получаю сообщение об ошибке:

Association references unmapped class: System.String

Как я могу сопоставить таблицу в коллекцию строк?

+0

Там В этом нет ничего плохого. Вы просто сопоставили его с одним-ко-многим, который работает только для списков сущностей. Взгляните на сторонников Дерека и Фредерикса. –

ответ

22

Я просто столкнулся с подобной ситуацией; и я обнаружил, что действительно можно отобразить коллекцию строк. Обратите внимание, что вам нужно сопоставить эти строки как объекты значений.

Это то, что у меня есть:

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

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

Mapping:

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

Совсем недавно появилось отображение FluentNHibernate, которое я использовал на основе вашего XML-сопоставления: mapping.HasMany (x => x.Synonyms) .AsBag(). Элемент ("ChapterCode", m => m.Type ()); – roryf

+0

Не должен ли ХашидСеть быть HashShet? –

+0

@roryf вы используете сумку, где должен быть комплект. Правильный код должен быть: HasMany (x => x.Synonyms) .Table («Синонимы»). AsSet(). Элемент («ChapterCode», m => m.Type () .Null.Nullable()); –

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 < строку > свойство как тип = "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(); 
    } 
7

Если я не ошибаюсь, вы можете сделать это:

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

идентичностей будучи IList<string>

Смежные вопросы