powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / WCF+Nhibernate+Oracle
9 сообщений из 9, страница 1 из 1
WCF+Nhibernate+Oracle
    #37436203
Hold Fast
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день, Господа!

Хочу поделиться своей проблемой и найти ее решение.
Есть некая служба на WCF c методом который принимает список объектов которые содержат коллекцию дочерних объектов. Суть метода состоит в том, чтобы вставлять и обновлять переданные объекты. Связь с БД осуществляется посредством Fluent Nhibernate. БД Oracle. Проблема возникает при обновлении сущностей в базе, а именно генерируется новый идентификатор записи т. е. происходит не обновление, а новая вставка. Код метода:

Код: plaintext
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.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
public void UploadPersons(List<Persona> persons)
        {
            try
            {
                var factory = GetFactory();

                using (var session = factory.OpenSession())
                {
                    using (var transaction = session.BeginTransaction())
                    {
                        foreach (var person in persons)
                        {
                            var oldPerson = session.Query<Persona>().SingleOrDefault(p => p.ID == person.ID);
                           
                            if (oldPerson != null)
                            {
                                person.PKId = oldPerson.PKId;

                                foreach (var relative in oldPerson.Relatives)
                                {
                                    session.Delete(relative);
                                }

                                session.Merge(person);
                            }
                            else
                            {
                                session.Save(person);
                            }

                            
                        }

                        transaction.Commit();
                    }
                }
            }
            catch (Exception ex)
            {
                var logWriter = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();
                logWriter.Write(ex);

                throw ex;
            }
        }


Я новичек в Nhibernate, до этого работал(аю) с EF, и никак не могу понять в чем собственно обстоит дело. Буду весьма признателен за все конструктивные предложения.
...
Рейтинг: 0 / 0
WCF+Nhibernate+Oracle
    #37436475
SolYUtor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Hold Fast,

1. Покажите маппинг Person.
2. Зачем вы делает это:
Код: plaintext
person.PKId = oldPerson.PKId;
?
...
Рейтинг: 0 / 0
WCF+Nhibernate+Oracle
    #37436612
Hold Fast
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
SolYUtor,

Код: plaintext
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.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
[DataContract]
    public class Relative
    {
        public virtual int Id { get; set; }

        [DataMember]
        public virtual Persona Persona { get; set; }
    }

   [DataContract(IsReference=true)]
    public class Persona
    {
        public Persona()
        {
            this.Relatives = new List<Relative>();
        }

        [DataMember]
        public virtual IList<Relative> Relatives
        {
            get;
            set;
        }


        public virtual int PKId { get; set; }
        
        [DataMember]
        public virtual Guid ID
        {
            get;
            set;
        }
     }

public class PersonaMapping : ClassMap<Persona>
    {
        public PersonaMapping()
        {
            this.Table("PERSONA");

            this.Id(p => p.PKId, "ID").GeneratedBy.TriggerIdentity();

            this.Map(p => p.ID, "ARM_ID");
           

            this.HasMany(x => x.Relatives)
                .KeyColumn("PERS_ID")
                .Fetch.Join()
                .Inverse()                
                .Cascade.All();
        }

public class RelativeMapping : ClassMap<Relative>
    {
        public RelativeMapping()
        {
            this.Table("FAM_MEMBERS");

            this.Id(r => r.Id).GeneratedBy.TriggerIdentity();

            this.References(r => r.Persona)
                .Column("PERS_ID")
                .Cascade.All();
        }
    }


Как то так...
...
Рейтинг: 0 / 0
WCF+Nhibernate+Oracle
    #37436625
Hold Fast
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
SolYUtor,

Код: plaintext
person.PKId = oldPerson.PKId;


это необходимо для того чтобы понять какую сущность обновлять в базе. потому что идентификаторы которые приходят с клиента и которые хранятся в БД отличаются. Приходится сохранять клиентский идентификатор в отдельном поле ARM_ID и при обновлении находить сущность по нему и брать идентификатор БД свойство PKId
...
Рейтинг: 0 / 0
WCF+Nhibernate+Oracle
    #37437096
SolYUtor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Hold Fast,

на вид всё выглядит правильно. Триггер точно не шалит?
...
Рейтинг: 0 / 0
WCF+Nhibernate+Oracle
    #37437464
Hold Fast
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
SolYUtor,

Оказалось вся проблема в этом:
Код: plaintext
1.
2.
3.
4.
foreach (var relative in oldPerson.Relatives)
{
     session.Delete(relative);
}

и в этом

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
public class RelativeMapping : ClassMap<Relative>
    {
        public RelativeMapping()
        {
            this.Table("FAM_MEMBERS");

            this.Id(r => r.Id).GeneratedBy.TriggerIdentity();

            this.References(r => r.Persona)
                .Column("PERS_ID")
                .Cascade.All();
        }
    }

нужно обнулять к каждого объекта Relative ссылку на персону, либо перенастроить маппинг, чтобы не было каскадного удаления.
...
Рейтинг: 0 / 0
WCF+Nhibernate+Oracle
    #37437695
SolYUtor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Hold Fast,

Да, как-то под вечер упустил момент с каскадным удалением. В таких случаях надо внимательнее следить, чтобы каскадные операции относились только к корню агрегата.
...
Рейтинг: 0 / 0
WCF+Nhibernate+Oracle
    #37438048
Hold Fast
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
SolYUtor,

Благодарю за участие.

Честно говоря Hibernate приятно удивил глубиной своей настройки, инструмент не детский :)
...
Рейтинг: 0 / 0
WCF+Nhibernate+Oracle
    #37438118
SolYUtor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Hold Fast,

Хороший инструмент, но только при правильном использовании. Удачи в освоении!
...
Рейтинг: 0 / 0
9 сообщений из 9, страница 1 из 1
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / WCF+Nhibernate+Oracle
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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