Как предотвратить ошибку синтаксиса SQL при отображении отношения один-ко-многим в Fluent NHibernate при использовании пользовательского класса коллекции? - PullRequest
1 голос
/ 01 апреля 2011

Я пытаюсь сопоставить отношение «один ко многим» в Fluent NHibernate, где свойство коллекции - это пользовательский класс коллекции. Я использую защищенное свойство InnerList в классе коллекции для предоставления коллекции, но получаю ошибку SQL при попытке сохранить элемент.

Класс Paragraph имеет свойство Elements типа ElementList. Сопоставление для этого:

public ParagraphMap()
{
    this.Id(x => x.Id);
    Component(
        x => x.Elements,
        m => m.HasMany<Element>(Reveal.Member<ElementList>("InnerList")).AsList().KeyColumn("ParagraphId").CollectionType<Element>());
}

Свойство InnerList класса ElementList:

protected List<Element> InnerList
{
    get { return this.list; }
    set { this.list = value; }
}

Я остановился на использовании расширения AsList для сопоставления и типа данных List для свойства InnerList из-за большого количества проб и ошибок при получении недопустимых ошибок приведения при использовании любых других типов данных.

При создании моего хранилища я получаю сообщение об ошибке «System.Data.SqlClient.SqlException: неверный синтаксис рядом с« Index ».».

Соответствующая часть сгенерированного SQL:

create table [Element] (
    Id INT IDENTITY NOT NULL,
   ParagraphId INT null,
   Index INT null,
   primary key (Id)
)

Что не так с моим отображением?

UPDATE: Теперь я вернулся к использованию массива вместо общего списка для свойства со следующим отображением в моем ParagraphMap:

Component(
    x => x.Elements,
    m => m.HasMany<Element>(Reveal.Member<ElementList>("InnerList")).AsArray(x => x.Id).KeyColumn("ParagraphId").Cascade.All());

Я больше не получаю ошибку SQL при создании базы данных, но все еще не могу добавить данные. При попытке добавить абзацы я получаю пустую ссылку:

var paragraph1 = new Paragraph(new element[] { new Element(), new Element() });
var paragraph2 = new Paragraph(new element[] { new Element(), new Element() });

using (var unitOfWork = this.repository.Begin())
{
    try
    {
        this.repository.Add(paragraph1);
        this.repository.Add(paragraph2);
    }
    catch (Exception)
    {
        unitOfWork.Rollback();
        throw;
    }

    unitOfWork.Commit();
}

Я предполагаю, что с отображением все еще что-то не так, но не знаю что.

UPDATE: Это трассировка стека для нулевой ссылки, которую я получаю при использовании Element [] в качестве моего типа в свойстве InnerList:

Execute
System.NullReferenceException: Object reference not set to an instance of an object.
   at NHibernate.Engine.Collections.ProcessReachableCollection(IPersistentCollection collection, CollectionType type, Object entity, ISessionImplementor session) in d:\CSharp\NH\nhibernate\src\NHibernate\Engine\Collections.cs:line 104
   at NHibernate.Event.Default.FlushVisitor.ProcessCollection(Object collection, CollectionType type) in d:\CSharp\NH\nhibernate\src\NHibernate\Event\Default\FlushVisitor.cs:line 40
   at NHibernate.Event.Default.AbstractVisitor.ProcessValue(Object value, IType type) in d:\CSharp\NH\nhibernate\src\NHibernate\Event\Default\AbstractVisitor.cs:line 51
   at NHibernate.Event.Default.AbstractVisitor.ProcessValue(Int32 i, Object[] values, IType[] types) in d:\CSharp\NH\nhibernate\src\NHibernate\Event\Default\AbstractVisitor.cs:line 37
   at NHibernate.Event.Default.AbstractVisitor.ProcessValues(Object[] values, IType[] types) in d:\CSharp\NH\nhibernate\src\NHibernate\Event\Default\AbstractVisitor.cs:line 32
   at NHibernate.Event.Default.AbstractVisitor.ProcessComponent(Object component, IAbstractComponentType componentType) in d:\CSharp\NH\nhibernate\src\NHibernate\Event\Default\AbstractVisitor.cs:line 77
   at NHibernate.Event.Default.AbstractVisitor.ProcessValue(Object value, IType type) in d:\CSharp\NH\nhibernate\src\NHibernate\Event\Default\AbstractVisitor.cs:line 59
   at NHibernate.Event.Default.AbstractVisitor.ProcessValue(Int32 i, Object[] values, IType[] types) in d:\CSharp\NH\nhibernate\src\NHibernate\Event\Default\AbstractVisitor.cs:line 37
   at NHibernate.Event.Default.AbstractVisitor.ProcessEntityPropertyValues(Object[] values, IType[] types) in d:\CSharp\NH\nhibernate\src\NHibernate\Event\Default\AbstractVisitor.cs:line 120
   at NHibernate.Event.Default.DefaultFlushEntityEventListener.OnFlushEntity(FlushEntityEvent event) in d:\CSharp\NH\nhibernate\src\NHibernate\Event\Default\DefaultFlushEntityEventListener.cs:line 58
   at NHibernate.Event.Default.AbstractFlushingEventListener.FlushEntities(FlushEvent event) in d:\CSharp\NH\nhibernate\src\NHibernate\Event\Default\AbstractFlushingEventListener.cs:line 161
   at NHibernate.Event.Default.AbstractFlushingEventListener.FlushEverythingToExecutions(FlushEvent event) in d:\CSharp\NH\nhibernate\src\NHibernate\Event\Default\AbstractFlushingEventListener.cs:line 60
   at NHibernate.Event.Default.DefaultAutoFlushEventListener.OnAutoFlush(AutoFlushEvent event) in d:\CSharp\NH\nhibernate\src\NHibernate\Event\Default\DefaultAutoFlushEventListener.cs:line 30
   at NHibernate.Impl.SessionImpl.AutoFlushIfRequired(ISet`1 querySpaces) in d:\CSharp\NH\nhibernate\src\NHibernate\Impl\SessionImpl.cs:line 1154
   at NHibernate.Impl.SessionImpl.List(IQueryExpression queryExpression, QueryParameters queryParameters, IList results) in d:\CSharp\NH\nhibernate\src\NHibernate\Impl\SessionImpl.cs:line 646
   at NHibernate.Impl.SessionImpl.List(IQueryExpression queryExpression, QueryParameters parameters) in d:\CSharp\NH\nhibernate\src\NHibernate\Impl\SessionImpl.cs:line 634
   at NHibernate.Impl.ExpressionQueryImpl.List() in d:\CSharp\NH\nhibernate\src\NHibernate\Impl\ExpressionQueryImpl.cs:line 63
   at NHibernate.Linq.NhQueryProvider.ExecuteQuery(NhLinqExpression nhLinqExpression, IQuery query, NhLinqExpression nhQuery) in d:\CSharp\NH\nhibernate\src\NHibernate\Linq\NhQueryProvider.cs:line 78
   at NHibernate.Linq.NhQueryProvider.Execute(Expression expression) in d:\CSharp\NH\nhibernate\src\NHibernate\Linq\NhQueryProvider.cs:line 27
   at NHibernate.Linq.NhQueryProvider.Execute[TResult](Expression expression) in d:\CSharp\NH\nhibernate\src\NHibernate\Linq\NhQueryProvider.cs:line 101
   at Remotion.Data.Linq.QueryableBase`1.GetEnumerator()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at Tests.WhenWorkingWithNHibernateRepository.CanGetAllParagraphs() in C:\test\Infrastructure\Infrastructure.Tests\Repository\WhenWorkingWithNHibernateRepository.cs:line 659

Ответы [ 4 ]

0 голосов
/ 18 марта 2013

Используйте следующую запись конфигурации

<property name="hbm2ddl.keywords">auto-quote</property>

Объяснение: NHibernate процитирует все имена таблиц / столбцов, которые соответствуют зарезервированным словам SQL, объявленным в используемом диалекте. Это особенно верно, когда вы обрабатываете отображение .AsList(), потому что оно добавляет столбец Index, который вы не можете контролировать (поэтому вы не можете переименовать).

0 голосов
/ 01 апреля 2011

У вас есть столбец , который называется Index , а Index - это зарезервированное слово (ключевое слово) в SQL, поэтому вам необходимо убедиться, что NHibernate экранирует этот столбец.

Когда вы определяете свои отображения в классических файлах hbm.xml, вы можете определить, что NHibernate должен экранировать этот столбец, сопоставляя его с помощью обратных галочек, например:

<property name="myProperty" column="`Index`" />

Итак, в Fluent NHibernate, в отображениигде вы сопоставляете свой класс с таблицей Element, попробуйте определить отображение следующим образом:

Map (x => x.MyProperty).Column ("`Index`");

(Обратите внимание, что обратные кавычки не равны кавычкам!)

При этом NHibernate сгенерируетоператор SQL, в котором экранирован столбец индекса;вот так, например:

SELECT Id, ParagraphId, [Index] FROM [Element]
0 голосов
/ 21 июля 2012

Это потому, что вы используете .AsList (),

попробуйте вместо этого использовать .AsBag ().

0 голосов
/ 01 апреля 2011

В элементе класса c # попробуйте переименовать целочисленное свойство c # Индекс до ElementIndex , чтобы проверить наличие конфликта имен.

...