Как сопоставить IDictionary‹string, string› с сопоставлением классов Fluent NHibernate и протестировать это сопоставление?

В моей саге MassTransit есть только одно поле, которое не будет отображаться правильно. Это -

    public virtual IDictionary<string, string> Rows
    {
        get { return _rows; }
        set { _rows = value; }
    }

Я пробовал отображать это несколькими способами -

    publich ProjCTSagaMap() // ctor for my ClassMap subclass
    {
        /*HasMany(x => x.Rows)
            .AsMap("ProjectNumber")
            .KeyColumns.Add("Row", mapping => mapping.Name("Row").SqlType("nvarchar").Not.Nullable())
            .Cascade.AllDeleteOrphan()
            .Table("ProjCtSagaRow");*/

        HasMany(x => x.Rows)
            .Table("ProjCtSagaRow")
            .KeyColumn("CorrelationId")
            .Element("Row")
            .AsMap("ProjectNumber")
            .Inverse();
    }

И я написал модульный тест для проверки отображения -

    [Test] public void ProjCtSagaMapTest()
    {
        using (var session = Utility.CreateSession<ProjCtSaga, ProjCtSagaMap>())
        {
            new PersistenceSpecification<ProjCtSaga>(session)
                .CheckReference(
                    i => i.Rows,
                    new Dictionary<string, string> { { "key", "value" } },
                    new DictionaryComparer<string, string>())
                .VerifyTheMappings();
        }

Я не уверен, где проблема на самом деле, в отображении или в тесте. Фактическая ошибка в модульном тесте -

NHibernate.MappingException occurred
  Message=No persister for: System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]
  Source=NHibernate
  StackTrace:
       at NHibernate.Impl.SessionFactoryImpl.GetEntityPersister(String entityName)
       at NHibernate.Impl.SessionImpl.GetEntityPersister(String entityName, Object obj)
       at NHibernate.Event.Default.AbstractSaveEventListener.SaveWithGeneratedId(Object entity, String entityName, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)
       at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event)
       at NHibernate.Event.Default.DefaultSaveEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event)
       at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.EntityIsTransient(SaveOrUpdateEvent event)
       at NHibernate.Event.Default.DefaultSaveEventListener.PerformSaveOrUpdate(SaveOrUpdateEvent event)
       at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.OnSaveOrUpdate(SaveOrUpdateEvent event)
       at NHibernate.Impl.SessionImpl.FireSave(SaveOrUpdateEvent event)
       at NHibernate.Impl.SessionImpl.Save(Object obj)
       at FluentNHibernate.Testing.PersistenceSpecification`1.TransactionalSave(Object propertyValue) in d:\Builds\FluentNH\src\FluentNHibernate\Testing\PersistenceSpecification.cs:line 79
  InnerException: 

Может ли кто-нибудь объяснить, как сопоставить IDictionary с ClassMap и проверить это сопоставление с помощью PersistenceSpecification... VerifyMappings()?

PS. Версия FluentNHibernate — 1.3.0.717, а версия NHibernate — 3.2.0.4000. Мне пришлось скомпилировать его локально для одного незначительного и несвязанного изменения.

Спасибо!


Вот остальная часть ошибки, которую я получаю сейчас -

System.FormatException : Failed to convert parameter value from a String to a Int32.
  ----> System.FormatException : Input string was not in a correct format.
at System.Data.SqlClient.SqlParameter.CoerceValue(Object value, MetaType destinationType)
at System.Data.SqlClient.SqlParameter.GetCoercedValue()
at System.Data.SqlClient.SqlParameter.Validate(Int32 index, Boolean isCommandProc)
at System.Data.SqlClient.SqlCommand.BuildParamList(TdsParser parser, SqlParameterCollection parameters)
at System.Data.SqlClient.SqlCommand.BuildExecuteSql(CommandBehavior behavior, String commandText, SqlParameterCollection parameters, ref _SqlRPC rpc)
at System.Data.SqlClient.SqlCommand.AddBatchCommand(String commandText, SqlParameterCollection parameters, CommandType cmdType)
at System.Data.SqlClient.SqlCommandSet.ExecuteNonQuery()
at NHibernate.AdoNet.SqlClientBatchingBatcher.DoExecuteBatch(IDbCommand ps)
at NHibernate.AdoNet.AbstractBatcher.ExecuteBatchWithTiming(IDbCommand ps)
at NHibernate.AdoNet.AbstractBatcher.ExecuteBatch()
at NHibernate.Engine.ActionQueue.ExecuteActions()
at NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource session)
at NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event)
at NHibernate.Impl.SessionImpl.Flush()
at NHibernate.Transaction.AdoTransaction.Commit()
at FluentNHibernate.Testing.PersistenceSpecification`1.TransactionalSave(Object propertyValue) in d:\Builds\FluentNH\src\FluentNHibernate\Testing\PersistenceSpecification.cs: line 80
at FluentNHibernate.Testing.PersistenceSpecification`1.VerifyTheMappings(T first) in d:\Builds\FluentNH\src\FluentNHibernate\Testing\PersistenceSpecification.cs: line 52
at Appalappa.Tests.ProjCtTests.ProjCtSagaMapTest() in ProjCtTests.cs: line 32
--FormatException
at System.Number.StringToNumber(String str, NumberStyles options, ref NumberBuffer number, NumberFormatInfo info, Boolean parseDecimal)
at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)
at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
at System.Data.SqlClient.SqlParameter.CoerceValue(Object value, MetaType destinationType)

person Bryan Edds    schedule 01.05.2012    source источник


Ответы (1)


избавьтесь от .Inverse();, так как элемент не может поддерживать обратную ссылку, это строка.

CheckReference для ссылок, но у вас есть коллекция. Используйте CheckEnumerable или CheckList

Обновление: это работает для меня

.CheckComponentList(p => p.Rows, 
                    new[] { new KeyValuePair<string, string>("1", "2") }, 
                    (p, item) => p.Rows.Add(item));
person Firo    schedule 03.05.2012
comment
Извините, а не могли бы вы привести пример использования CheckList или CheckReference в этом случае? Я пробовал .CheckList(i => i.Rows, new Dictionary<string, string> { { "key", "value" } }), но выдает только исключение NHibernate.MappingException : No persister for: System.Collections.Generic.KeyValuePair`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]. - person Bryan Edds; 07.05.2012
comment
Итак, я сделал именно так, как вы рекомендовали, но я получаю следующее исключение - System.FormatException : Failed to convert parameter value from a String to a Int32. ----> System.FormatException : Input string was not in a correct format. at System.Data.SqlClient.SqlParameter.CoerceValue(Object value, MetaType destinationType). Трассировка стека вставляется во вставленный в исходный пост. - person Bryan Edds; 09.05.2012
comment
к сожалению, это похоже на ошибку в FNH, поскольку он пытается сопоставить строковый ключ с целочисленным столбцом. .AsMap‹string›(ProjectNumber) должен решить эту проблему. - person Firo; 09.05.2012