Проблема NHibernate с назначенным идентификатором строки и различными символами регистра - PullRequest
3 голосов
/ 31 мая 2011

У меня проблема при сохранении сущности с присвоенным ей строковым идентификатором в NHibernate ... Я пытаюсь объяснить проблему на примере.

Хорошо, предположим, что в базе данных есть сущность с идентификатором "AAA", если я выполню эти операторы

ENTITYTYPE entity = Session.Get<ENTITYTYPE>("AAA");
ENTITYTYPE newentity = new ENTITYTYPE() { Id = "aaa" };

Session.Delete(entity);
Session.Save(newentity);
Session.Flush();

На Flush NHibernate вызовет исключение с этим сообщением:" Не удалось синхронизировать состояние базы данных с сеансом "/" Нарушение PRIMARY KEY "

Кажетсячтобы у меня была проблема с чувствительным к регистру идентификатором, если я использую «AAA» для идентификатора «newentity», то это работает, но в моей ситуации это не так просто, и я должен найти альтернативное решение.

Как можноизбежать этого исключения?Вы можете мне помочь?

1 Ответ

2 голосов
/ 31 мая 2011

Я не знаю, достаточно ли этого, но вы управляете им с помощью чего-то вроде этого:

public override bool Equals(object obj)
{
T other = obj as T;
if (other == null)
    return false;

// handle the case of comparing two NEW objects
bool otherIsTransient = Equals(other.Id, Guid.Empty);
bool thisIsTransient = Equals(Id, Guid.Empty);
if (otherIsTransient && thisIsTransient)
    return ReferenceEquals(other, this);

return other.Id.ToUpper().Equals(Id.ToUpper());
}

с помощью метода ToUpper () или ToLower () во время сравнения вашей сущности, или вы можете использовать String.Compare (stringA, strngB, StringComparison.OrdinalIgnoreCase).

Если вы хотите больше контроля и если это ваша цель, вы можете создать свой собственный генератор Id, как описано здесь:

http://nhibernate.info/doc/howto/various/creating-a-custom-id-generator-for-nhibernate.html

обновлено

вы пытались создать пользовательский GetIgnoreCase (...)?

Я думаю, что также возможно переопределить оператор SELECT, сгенерированный по умолчаниюПолучите метод в вашем файле отображения сущностей через тег загрузчика, как в этом примере:

       ...
      <loader query-ref="loadProducts"/>
 </class>

 <sql-query name="loadProducts">
 <return alias="prod" class="Product" />
 <![CDATA[
  select 
    ProductID as {prod.ProductID}, 
    UnitPrice as {prod.UnitPrice}, 
    ProductName as {pod.ProductName}
  from Products prod
  order by ProductID desc
]]>

Вы можете попытаться изменить оператор select, возвращая идентификатор в верхнем регистре.

обновлено

После дальнейшего расследования я думаю, что способом решения вашей проблемы может быть использование перехватчика!

Читайте здесь:

http://knol.google.com/k/fabio-maulo/nhibernate-chapter-11-interceptors-and/1nr4enxv3dpeq/14#

здесь больше документов:

http://blog.scooletz.com/2011/02/22/nhibernate-interceptor-magic-tricks-pt-5/

Something like это:

 public class TestInterceptor
  : EmptyInterceptor, IInterceptor
{
    private readonly IInterceptor innerInterceptor;

    public TestInterceptor(IInterceptor innerInterceptor)
    {
        this.innerInterceptor = this.innerInterceptor ?? new EmptyInterceptor();
    }

    public override object GetEntity(string entityName, object id)
    {
        if (id is string)
            id = id.ToString().ToUpper();

        return this.innerInterceptor.GetEntity(entityName, id);

    }

}

и зарегистрируйте его свободно, как это:

return Fluently.Configure()
           ...
            .ExposeConfiguration(c =>{c.Interceptor = new TestInterceptor(c.Interceptor ?? new EmptyInterceptor());})
            ...
            .BuildConfiguration();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...