Гость
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / NHibernate: генерация кастомного ID / 25 сообщений из 37, страница 1 из 2
12.12.2012, 20:36
    #38076571
Alexvmk
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
NHibernate: генерация кастомного ID
Всем привет!
Есть следующая задачка.
Есть распределенная 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
12.12.2012, 21:56
    #38076663
МСУ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
NHibernate: генерация кастомного ID
...
Рейтинг: 0 / 0
12.12.2012, 22:26
    #38076712
Alexvmk
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
NHibernate: генерация кастомного ID
Спасибо, а на Fluent, как написать не в курсе случайно? Че то примеров в инете ваще нет.
...
Рейтинг: 0 / 0
12.12.2012, 22:30
    #38076715
МСУ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
NHibernate: генерация кастомного ID
Код: c#
1.
2.
Id( x => x.Id ).GeneratedBy.Custom<NHibernate.Id.TriggerIdentityGenerator>(); 
Id( x => x.Id ).GeneratedBy.Custom<My.Namespace.MyIdentifierGenerator>();
...
Рейтинг: 0 / 0
12.12.2012, 23:20
    #38076789
Alexvmk
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
NHibernate: генерация кастомного ID
Большое спасибо!
Сейчас попробую кастомную генерацию, но в таком случае надо будет делать запрос к секвенсу.

Не знаете, почему ошибка 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
12.12.2012, 23:47
    #38076823
Alexvmk
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
NHibernate: генерация кастомного ID
Блин, что-то не получается с кастомным(
Делаю генератор:
Код: 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
13.12.2012, 00:01
    #38076838
Alexvmk
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
NHibernate: генерация кастомного ID
AlexvmkБлин, что-то не получается с кастомным(
........

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

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


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

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

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


через fluent nhibernate можно как-то? или уж только через ADO тут..
...
Рейтинг: 0 / 0
13.12.2012, 00:02
    #38076841
Где-то в степи
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
NHibernate: генерация кастомного ID
Alexvmk,
вот что то не пойму , пож уточните
у вас есть таблица с полем- уникальным идентификатором этой таблицы, вы вводите еще дополнительное поле для идентификации записи относительно всей базы
уникальное поле для таблицы вы генерите с наружи - назначенное, а добавочное генерите в базе данных тригером.
так?
если так то постзапросом select lastval вы никогда не получите уникальное поле всей базы, вернется значение уникального
поля таблицы которое вы назначили с наружи, если вам надо будет узнать уникальное поле для все базы, вам надо будет тянуть всю запись на клиента.
...
Рейтинг: 0 / 0
13.12.2012, 09:14
    #38077021
МСУ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
NHibernate: генерация кастомного ID
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
13.12.2012, 10:55
    #38077152
Alexvmk
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
NHibernate: генерация кастомного ID
Где-то в степиAlexvmk,
вот что то не пойму , пож уточните
у вас есть таблица с полем- уникальным идентификатором этой таблицы, вы вводите еще дополнительное поле для идентификации записи относительно всей базы
уникальное поле для таблицы вы генерите с наружи - назначенное, а добавочное генерите в базе данных тригером.
так?
если так то постзапросом select lastval вы никогда не получите уникальное поле всей базы, вернется значение уникального
поля таблицы которое вы назначили с наружи, если вам надо будет узнать уникальное поле для все базы, вам надо будет тянуть всю запись на клиента.

Доброе утро, Вы не правильно поняли. Во-первых, дополнительные поля я не использую.
Я бы все хотел бы генерить в триггере: а в программе просто получать значение ID. Но NHibernate выдает ошибку при trigger-identity генераторе:(
...
Рейтинг: 0 / 0
13.12.2012, 10:56
    #38077153
Alexvmk
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
NHibernate: генерация кастомного ID
МСУ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
13.12.2012, 11:17
    #38077190
Где-то в степи
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
NHibernate: генерация кастомного ID
Alexvmk,
Понял
ТОгда это проблемы посгресса, почему он выхватывает поле не за пределами внутренней транзакции.
по второму
Это очень разумно, пускай сама база заботится по уникальности, но тогда этот ключ будет на кастомным, а простым as автоинкремент и часть обязанностей с клиента снимается.
...
Рейтинг: 0 / 0
13.12.2012, 11:30
    #38077225
МСУ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
NHibernate: генерация кастомного ID
AlexvmkМСУ, я имею ввиду сделать самому запрос в коде метода custom генератора, чтобы к этому значению я еще прибавил код БД справа.
Вот пример

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

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

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

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

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

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

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

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


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