powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / NHibernate: генерация кастомного ID
25 сообщений из 37, страница 1 из 2
NHibernate: генерация кастомного ID
    #38076571
Alexvmk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Всем привет!
Есть следующая задачка.
Есть распределенная POSTGRESQL БД. То есть есть ЦБД и множество БД. Все они имеют одинаковую структуру и данные в них синхронизируются.
Соответственно встала задача уникальности каждой записи в таблице в рамках всей распределенной БД.

Программа, которая работает с базами данных написана на C# и использует Fluent NHibernate. То есть все общение с данными через NHibernate происходит.

Так вот задачу уникальности я решил делать так:
у каждой БД есть номер org_id. Также для таблиц есть сиквенс. Генерим ID с помощью сиквенса, а далее вычисляем окончательное значение ID, как ID * 1000 + org_id. Все это генерим в Before Insert триггерах к таблицам.

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
-- This is script that creates identity triggers for all tables.
CREATE OR REPLACE FUNCTION GetOrganizationId() RETURNS bigint AS $$
    select CAST(value AS bigint) from public.setting set
    WHERE upper(set.name) = upper('org_id');
  $$ LANGUAGE SQL;

  CREATE OR REPLACE FUNCTION GetId(Id bigint) RETURNS bigint AS $$
    select Id * 1000 + GetOrganizationId() AS result;
  $$ LANGUAGE SQL;
  
  
  ----------------production_type:--------------------------------------
  CREATE SEQUENCE production_type_id_seq
  INCREMENT 1
  MINVALUE 1
  MAXVALUE 9223372036854775807
  START 1
  CACHE 1;
  
  CREATE OR REPLACE FUNCTION production_type_identity() RETURNS trigger AS $production_type_identity$
    BEGIN
    
        IF NEW.ID IS NULL THEN
            NEW.ID := GetId(nextval('production_type_id_seq'));
        END IF;
        RETURN NEW;
    END;
  $production_type_identity$ LANGUAGE plpgsql;

  CREATE TRIGGER production_type_identity BEFORE INSERT ON production_type
    FOR EACH ROW EXECUTE PROCEDURE production_type_identity();  
  ------------------------------------------------------



Так вот проблема в том, что NHibernate не получает новое значение сгенерированное в триггере.
Юзал стандартный тип генерации:
Код: c#
1.
2.
3.
4.
5.
protected BaseMap()
        {
            Id(x => x.Id);
            Map(x => x.ObjectVersion, "OBJECT_VERSION").Not.Nullable();
......


в этом случае после инсерта ОРМ делает select lastval() - а это последнее значение выбранное из сиквенса за текущую сессию, соот-но он без номера бд.

Также юзал и trigger-identity тип генерации, который как раз для триггеров before insert сделан:
Код: c#
1.
Id(x => x.Id).GeneratedBy.TriggerIdentity();


тут я получаю ошибку "nhibernate assertionfailure null identifier".

Братья и сестры, добрые, помогите, уже два дня гуглю. Ниче не нашел(
Может быть альтернативное решение подскажите...
...
Рейтинг: 0 / 0
NHibernate: генерация кастомного ID
    #38076663
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
NHibernate: генерация кастомного ID
    #38076712
Alexvmk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо, а на Fluent, как написать не в курсе случайно? Че то примеров в инете ваще нет.
...
Рейтинг: 0 / 0
NHibernate: генерация кастомного ID
    #38076715
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: c#
1.
2.
Id( x => x.Id ).GeneratedBy.Custom<NHibernate.Id.TriggerIdentityGenerator>(); 
Id( x => x.Id ).GeneratedBy.Custom<My.Namespace.MyIdentifierGenerator>();
...
Рейтинг: 0 / 0
NHibernate: генерация кастомного ID
    #38076789
Alexvmk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Большое спасибо!
Сейчас попробую кастомную генерацию, но в таком случае надо будет делать запрос к секвенсу.

Не знаете, почему ошибка NHibernate.AssertionFailure: null identifier возникает при TriggerIdentityGenerator:
Код: c#
1.
Id(x => x.Id).GeneratedBy.Custom<NHibernate.Id.TriggerIdentityGenerator>();


и как можно было бы ее обойти? Это баг NHibernat'а?

Ккстати, интересно, что ,если смотреть в профайлере NHibernate sql, то там следующее:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
INSERT INTO ROLE (
	OBJECT_VERSION,
	 OBJECT_CREATE_DATE,
	 OBJECT_EDIT_DATE,
	 CREATE_USER,
	 EDIT_USER,
	 NAME,
	 ACCESS_TO_CASHIER,
	 ACCESS_TO_ROLES)
 VALUES (
	0 /* :p0 */,
	 '2012-12-12T23:15:35.00' /* :p1 */,
	 '2012-12-12T23:15:35.00' /* :p2 */,
	 NULL /* :p3 */,
	 NULL /* :p4 */,
	 '1Супер кассир' /* :p5 */,
	 0 /* :p6 */,
	 'False [Type: Boolean (0)], :nhIdOutParam = NULL' /* :p7 */)
 returning Id


...Какой-то странный sql формируется....

далее профайлер пишет:
ERROR:
Код: plsql
1.
An AssertionFailure occurred - this may indicate a bug in NHibernate or in your custom types.



Почему так?
...
Рейтинг: 0 / 0
NHibernate: генерация кастомного ID
    #38076823
Alexvmk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Блин, что-то не получается с кастомным(
Делаю генератор:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
public class MyGenerator : IIdentifierGenerator
    {
        readonly Random _rnd1 = new Random();

        public object Generate(ISessionImplementor session, object obj)
        {
            return _rnd1.Next();
        }
    }



Описываю мэппинг ID:
Код: c#
1.
Id(x => x.Id).GeneratedBy.Custom<MyGenerator>();



При создании записи выходит ошибка:
Код: c#
1.
Nhibernate.HibernateException: identifier of an instance of Canteen.Entities.Role was altered from 394866042 to 394866042



Что не так сделал?
...
Рейтинг: 0 / 0
NHibernate: генерация кастомного ID
    #38076838
Alexvmk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
AlexvmkБлин, что-то не получается с кастомным(
........

Что не так сделал?

Последний вопрос снимаю...
у меня ID все в меппинге типа long. Изменил генератор на
Код: c#
1.
return Convert.ToInt64(_rnd1.Next());


и все ок, создалась запись.

Остается вопрос по trigger-identity: можно ли все-таки обойти ту ошибку и юзать триггеры СУБД?

Также вопрос, как просто сделать запрос на получение следующего значения сиквенса в генераторе
Код: c#
1.
select nextval('table_id_seq')


через fluent nhibernate можно как-то? или уж только через ADO тут..
...
Рейтинг: 0 / 0
NHibernate: генерация кастомного ID
    #38076841
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexvmk,
вот что то не пойму , пож уточните
у вас есть таблица с полем- уникальным идентификатором этой таблицы, вы вводите еще дополнительное поле для идентификации записи относительно всей базы
уникальное поле для таблицы вы генерите с наружи - назначенное, а добавочное генерите в базе данных тригером.
так?
если так то постзапросом select lastval вы никогда не получите уникальное поле всей базы, вернется значение уникального
поля таблицы которое вы назначили с наружи, если вам надо будет узнать уникальное поле для все базы, вам надо будет тянуть всю запись на клиента.
...
Рейтинг: 0 / 0
NHibernate: генерация кастомного ID
    #38077021
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlexvmkТакже вопрос, как просто сделать запрос на получение следующего значения сиквенса в генераторе
Код: c#
1.
select nextval('table_id_seq')


через fluent nhibernate можно как-то? или уж только через ADO тут..

Конечно можно. Через маппинги:

Код: xml
1.
2.
3.
4.
5.
6.
<id type="long">
      <generator class="native">
          <param name="sequence">cust_id_seq</param>
      <param name="parameters">START WITH 10</param>
      </generator>
</id>
...
Рейтинг: 0 / 0
NHibernate: генерация кастомного ID
    #38077152
Alexvmk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Где-то в степиAlexvmk,
вот что то не пойму , пож уточните
у вас есть таблица с полем- уникальным идентификатором этой таблицы, вы вводите еще дополнительное поле для идентификации записи относительно всей базы
уникальное поле для таблицы вы генерите с наружи - назначенное, а добавочное генерите в базе данных тригером.
так?
если так то постзапросом select lastval вы никогда не получите уникальное поле всей базы, вернется значение уникального
поля таблицы которое вы назначили с наружи, если вам надо будет узнать уникальное поле для все базы, вам надо будет тянуть всю запись на клиента.

Доброе утро, Вы не правильно поняли. Во-первых, дополнительные поля я не использую.
Я бы все хотел бы генерить в триггере: а в программе просто получать значение ID. Но NHibernate выдает ошибку при trigger-identity генераторе:(
...
Рейтинг: 0 / 0
NHibernate: генерация кастомного ID
    #38077153
Alexvmk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
МСУAlexvmkТакже вопрос, как просто сделать запрос на получение следующего значения сиквенса в генераторе
Код: c#
1.
select nextval('table_id_seq')


через fluent nhibernate можно как-то? или уж только через ADO тут..

Конечно можно. Через маппинги:

Код: xml
1.
2.
3.
4.
5.
6.
<id type="long">
      <generator class="native">
          <param name="sequence">cust_id_seq</param>
      <param name="parameters">START WITH 10</param>
      </generator>
</id>


МСУ, я имею ввиду сделать самому запрос в коде метода custom генератора, чтобы к этому значению я еще прибавил код БД справа.
...
Рейтинг: 0 / 0
NHibernate: генерация кастомного ID
    #38077190
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexvmk,
Понял
ТОгда это проблемы посгресса, почему он выхватывает поле не за пределами внутренней транзакции.
по второму
Это очень разумно, пускай сама база заботится по уникальности, но тогда этот ключ будет на кастомным, а простым as автоинкремент и часть обязанностей с клиента снимается.
...
Рейтинг: 0 / 0
NHibernate: генерация кастомного ID
    #38077225
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlexvmkМСУ, я имею ввиду сделать самому запрос в коде метода custom генератора, чтобы к этому значению я еще прибавил код БД справа.
Вот пример

http://blog.anorakgirl.co.uk/2009/01/custom-hibernate-sequence-generator-for-id-field/
...
Рейтинг: 0 / 0
NHibernate: генерация кастомного ID
    #38077246
Alexvmk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
МСУAlexvmkМСУ, я имею ввиду сделать самому запрос в коде метода custom генератора, чтобы к этому значению я еще прибавил код БД справа.
Вот пример

http://blog.anorakgirl.co.uk/2009/01/custom-hibernate-sequence-generator-for-id-field/

Спасибо, сегодня вечером буду пробовать подобное написать на C#.
...
Рейтинг: 0 / 0
NHibernate: генерация кастомного ID
    #38077527
SolYUtor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexvmk,

а стоит ли вам мегакастомый генератор затраченных на него усилий?
...
Рейтинг: 0 / 0
NHibernate: генерация кастомного ID
    #38077554
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SolYUtorAlexvmk, а стоит ли вам мегакастомый генератор затраченных на него усилий?
Да какой это мегакатомный, несколько строк кода. Банальный генератор ведь.
...
Рейтинг: 0 / 0
NHibernate: генерация кастомного ID
    #38077565
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
МСУSolYUtorAlexvmk, а стоит ли вам мегакастомый генератор затраченных на него усилий?
Да какой это мегакатомный, несколько строк кода. Банальный генератор ведь.
а зачем он вообще нужен, если предположить а потом исполнить все это внутрях базы без участия клиента?
...
Рейтинг: 0 / 0
NHibernate: генерация кастомного ID
    #38077578
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
разве guid ЗАПИСИ не будет уникальным для всех записей базы, или я опять чето не понял?
...
Рейтинг: 0 / 0
NHibernate: генерация кастомного ID
    #38077590
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Где-то в степи, не в уникальности дело, а в том, чтобы отруливать идентификаторами по, например, маске :)
...
Рейтинг: 0 / 0
NHibernate: генерация кастомного ID
    #38077842
Alexvmk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
SolYUtorAlexvmk,

а стоит ли вам мегакастомый генератор затраченных на него усилий?
Неособо же и это мегаксотмный.
А какое Вы предложите решение для задачи уникальности ID в рамках целой распределенной БД (много отдельных баз) с учетом того, что работаем с postgres + С# + NHibernate?
...
Рейтинг: 0 / 0
NHibernate: генерация кастомного ID
    #38077851
Alexvmk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Где-то в степиМСУпропущено...

Да какой это мегакатомный, несколько строк кода. Банальный генератор ведь.
а зачем он вообще нужен, если предположить а потом исполнить все это внутрях базы без участия клиента?
Без клиента то без клиента, но на клиенте то нам нужно сгенерированный id как-то получить. Не делать же запрос по наименованию получать id.....
Я вот и попытался без участия клиента..но не вышло, так как trigger-identity у NHibernate глючит.
...
Рейтинг: 0 / 0
NHibernate: генерация кастомного ID
    #38077865
Alexvmk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Где-то в степиразве guid ЗАПИСИ не будет уникальным для всех записей базы, или я опять чето не понял?
Я не буду с GUID работать - только long. Да, и учтите, что уникальными записи в одной таблице должны быть не только в рамках одной БД, а в рамках всех баз данных распределенной системы сюда входят базы региона: бд города Н, БД города К, ЦБД региона и т д).
...
Рейтинг: 0 / 0
NHibernate: генерация кастомного ID
    #38078147
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexvmk,
не хотите с guid, работайте с лонгом, на сервере можно легко получить уникальное значение записи, в контексте всех хранилищ
если количество баз известно, впрочем можно и без, select lastval вернет вам это значение после вставки, клиенту
вообще этот механизм должен быть неизвестен, и не к чему.
...
Рейтинг: 0 / 0
NHibernate: генерация кастомного ID
    #38078160
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
МСУГде-то в степи, не в уникальности дело, а в том, чтобы отруливать идентификаторами по, например, маске :)
дак это можно получить с помощью хешбазы + хештаблцы+ хешguidзаписи. не?
...
Рейтинг: 0 / 0
NHibernate: генерация кастомного ID
    #38078194
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Где-то в степиМСУГде-то в степи, не в уникальности дело, а в том, чтобы отруливать идентификаторами по, например, маске :)
дак это можно получить с помощью хешбазы + хештаблцы+ хешguidзаписи. не?
Причем тут маска и "хешбазы + хештаблцы+ хешguidзаписи"?
Я хочу, например, такой ID: [ddMMyyyy][sequence_num][запрос_из_вебсервиса_получение_некоего_спецномера][случайный_символ_из_строки_АБВГДЕЁЖЗИКЛМНОПРСТУФХЦЧШЩЭЮЯ][текущее_время]

1. Можно сделать это через триггер, но это зло и некроссплатформенно
2. Можно апдейтить после вставки - убого и 2 батча
3. Можно сделать через нативный инструмент ORM'а - IIdentifierGenerator

Еще раз, вопрос не в уникальности стоит, а в формате.
...
Рейтинг: 0 / 0
25 сообщений из 37, страница 1 из 2
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / NHibernate: генерация кастомного ID
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]