powered by simpleCommunicator - 2.0.52     © 2025 Programmizd 02
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / Общий предок для всех Entity (NHibernate) - не работает получение типа под прокси
17 сообщений из 17, страница 1 из 1
Общий предок для всех Entity (NHibernate) - не работает получение типа под прокси
    #37293052
NHibernate_User_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день,
Есть такая замечательная книжка, NHibernate CookBook, вроде как уже адаптированная под NH 3.0, у нас в проекте правда 2.0, но вряд ли это что-то изменит.

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

Главным образом пришлось заюзать его из-за следующей цепочки: есть связи М:М -> не нужны лишние insert и delete при каждом обновлении коллекции -> пришлось использовать <set> и ISet (Iesi) -> нужно перегрузить для таких коллекций Equals -> кто ж как не авторы NHibernate знают, как это правильней сделать? -> использовать пример из их книжки NHibernate 3.0 CookBook (по крайней мере лидер команды NH и еще один член участвовали в разработке книги).

Вот оно:
Код: 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.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
using System;

namespace blablabla
{
    public abstract class Entity<TId>
    {
        public virtual TId Id { get; /*protected*/ set; }

        public override bool Equals(object obj)
        {
            return Equals(obj as Entity<TId>);
        }

        private static bool IsTransient(Entity<TId> obj)
        {
            return obj != null &&
            Equals(obj.Id, default(TId));
        }

        private Type GetUnproxiedType()
        {
            return GetType();
        }

        public virtual bool Equals(Entity<TId> other)
        {
            if (other == null)
                return false;
            if (ReferenceEquals(this, other))
                return true;
            if (!IsTransient(this) &&
            !IsTransient(other) &&
            Equals(Id, other.Id))
            {
                var otherType = other.GetUnproxiedType();
                var thisType = GetUnproxiedType();
                return thisType.IsAssignableFrom(otherType) ||
                otherType.IsAssignableFrom(thisType);
            }
            return false;
        }

        public override int GetHashCode()
        {
            if (Equals(Id, default(TId)))
                return base.GetHashCode();
            return Id.GetHashCode();
        }

        /// <summary>
        /// Данный метод не из книжки, его добавил я.
        /// Проверка двух entity на равенство. Используется при перегрузке оператора ==
        /// Если одна из них Null, а другая нет, то они не равны. Два null равны.
        /// </summary>
        /// <typeparam name="TEntity">Тип entity</typeparam>
        protected static bool AreEqual<TEntity>(TEntity entity1, TEntity entity2)
        {
            if ((object)entity1 == null)
            {
                return ((object)entity2 == null);
            }
            else
            {
                return entity1.Equals(entity2);
            }
        }

        /// <summary>
        /// Данный метод не из книжки, его добавил я.
        /// Проверка двух entity на неравенство. Используется при перегрузке оператора !=
        /// </summary>
        /// <typeparam name="TEntity">Тип entity</typeparam>
        protected static bool AreNotEqual<TEntity>(TEntity entity1, TEntity entity2)
        {
            return !AreEqual(entity1, entity2);
        }
    }
}

Типичный пример использования:

Код: 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.
using System;
using System.Collections.Generic;
using Iesi.Collections.Generic;
using ERP.Infrastructure.Entities;

namespace ERP.Wholesale.Domain.Entities
{
    public abstract class Organization : Entity<int>
    {
        #region Методы

        #region Перегрузка равенства, Equals и GetHashCode

        public override bool Equals(object obj)
        {
            return base.Equals(obj);
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        public static bool operator ==(Organization object1, Organization object2)
        {
            return AreEqual(object1, object2);
        }

        public static bool operator !=(Organization object1, Organization object2)
        {
            return AreNotEqual(object1, object2);
        }

        #endregion

        #endregion
    }
}

Беда в том, что иногда метод GetUnproxiedType() выдает все же тип прокси!
Из-за этого метод Equals() выдал для двух entities с одинаковым id (когда после коммита unitofwork NH пытался писать в entity - в одно из полей то же самое значение, что и было), что они не равны.

Полная печаль :(

Как делают это профессионалы?

Думал я, что тот пример Entity<> не умеет работать с наследованием, но он в той части книги, где как раз наследование есть.

Реально у нас от Organization произошла COrganization, а от той - DOrganization. Вот создавалась связь этой DOrganization

Мы можем сделать виртуальный метод Get...Type в базовой Entity, а потом его перегружать, но стоит ли?

Реально у нас был сеттер одного из полей для защиты (раз уж сделали метод, меняющий поле, public в предыдущем примере от случайного изменения этого поля извне (по логике работы оно инициализировалось один раз при создании объекта и более не трогалось):
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
public class Contract: Entity <short>
{
        public virtual COrganization COrganization
        {
            get { return cOrganization; }
            protected internal set
            {
                if (cOrganization != null && value != cOrganization) // != вызывает ==, которое вызывает Equals, который выз.GetUnproxiedType()
                        throw new Exception("Невозможно сменить организацию.");
                }
                cOrganization = value;
            }
        }
        private COrganization cOrganization;
}

Вот конструировали новый Contract, который при конструировании ставил свое поле COrganization указывать на некую организацию. (И добавлял себя в коллекцию этой организации). Потом делали UnitOfWork.Commit, NH лезло в поле, писало в это поле организацию с тем же id, глючил GetUnproxiedType, потом неправильно они считались не равными, и сеттер ругался...

Можно, конечно, не пользовать операцию != для сущности, раз она глючит, и обойтись лямбдой: (... && value != null && value.Id != cOrganization.Id). Но как-то все равно нехорошо :( Например, теоретически в коллекцию может добавиться двойной элемент (с одним Id, а NH подумает, что он не равен сам себе, как сейчас). Ошибка будет где-то на уровне SQL, я думаю. Мы конечно будем руками через лямбды каждый раз проверять, есть ли элемент с таким Id в коллекции, но все равно как-то грустно. Сейчас надо весь проект переделать под новое Entity<>, а переделывать его на неработающий код как-то не лежит душа :(
...
Рейтинг: 0 / 0
Общий предок для всех Entity (NHibernate) - не работает получение типа под прокси
    #37293226
NHibernate_User_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вот этот поганец в методе Entity.Equals(Entity<TId> other) :
Код: plaintext
1.
2.
3.
4.
5.
                var otherType = other.GetUnproxiedType();
                var thisType = GetUnproxiedType();

                return thisType.IsAssignableFrom(otherType) ||
                otherType.IsAssignableFrom(thisType);

собственно otherType == COrganizationProxy
thisType == DOrganization
От COrganization произошли COrganizationProxy и DOrganization.
Естественно, что они не являются IsAssignableFrom друг друга...

Может, не стОило делать перегрузку операций != == Equals GetHashCode у потомков базового Entity? В книге вроде только для базового определено оно... Но у нас уж для пары классов она была перегружена, так чтобы не убирать == и != по всему проекту для данных entity, пришлось в них переделать == и != с учетом нового Equals.
...
Рейтинг: 0 / 0
Общий предок для всех Entity (NHibernate) - не работает получение типа под прокси
    #37293616
NHibernate_User_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Так заменить obj == obj на obj.id == obj.id это полдела.
У нас широко используются Contains, Intersect.
Тема уже обсуждалась, даже говорили, что все работает.
Но мне совершенно непонятно, как может с прокси корректно работать такой пример оттуда:
Код: plaintext
1.
2.
      if ( obj.GetType() != typeof( Myobj ) ) return false;
      return Equals( (Myobj)obj );
если даже приведенный мною выше пример из книжки NH CookBook не работает.
...
Рейтинг: 0 / 0
Общий предок для всех Entity (NHibernate) - не работает получение типа под прокси
    #37299464
OVoronov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Видимо, все, что могу предложить - раз все уперлось в неправильное определение типа под прокси - можно 100% решить данную проблему путем введения в Entity виртуального метода Type GetUnproxiedType() и переопределять его во всех потомках, а в самом Entity его и определять не нужно. (Или пусть возвращает null, т.о. если забудем метод переопределить в потомке, он проверит и кинет исключение). Еще подводный камень, что в более далеких коленах наследования можно забыть переопределить его, и они будут неправильно возвращать тип предка. Выглядит костылем, но должно работать

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
class COrganization
{
  override Type GetUnproxiedType()
  {
    return typeof (COrganization);
  }
}

Может, можно как-то попытаться извратиться через genericи. Только не уверен, сработает ли
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Entity<TId, Tentity>
{
public virtual TId Id { get; /*protected*/ set; } // - хехе, любой может сломать, и не только entity
public virtual Type GetUnproxiedType ()
{
  return typeof(Tentity);
}
}
// использовать:
class COrganization : Entity<Guid, COrganization>

Странно, что такая книга от самих авторов NHibernate ввела в такой тупик. Может быть, они не тестировали свой код на сложных иерархиях классов?

Осталось ждать только веского слова Solyutorа... Уж он скажет, так скажет. Хотелось бы знать, что он думает по поводу примера entity из данной книги.


public virtual bool Equals(Entity<TId> other) - что-то меня терзают подозренья, что авторы не зря сделали этот метод public, хотя могли бы private. Хотят, чтобы мы переопределяли его в каждом потомке, что ли? Может, в этом все дело?
...
Рейтинг: 0 / 0
Общий предок для всех Entity (NHibernate) - не работает получение типа под прокси
    #37299981
SolYUtor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Давайте по порядку.
Начнём с прокси. Пример из книжки мне представляется вводящей в заблуждение ошибкой:
Код: plaintext
1.
2.
3.
 private Type GetUnproxiedType()
{
    return GetType();
}
Этот код в принципе не может дать распроксированный тип, т.к. GetType() невиртуальный, и всегда возвратит тип объекта. И в этом можно убедиться самостоятельно.
Если уж очень хочется узнать настоящий тип, можно использовать статический класс NHibernateProxyHelper. Там уже есть нужные методы расширения.

По поводу эквивалентности - я использую этот базовый класс . Но он тоже выдаст false при сравнении прокси/непрокси объектов. Его можно модифицировать для сравнения и прокси объектов, но тогда в вашей модели будут явные ссылки на NHibernate (см. класс выше.)
...
Рейтинг: 0 / 0
Общий предок для всех Entity (NHibernate) - не работает получение типа под прокси
    #37301133
OVoronov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вот то-то и оно, только без связывания (полного) entity с NHibernate можно обойтись, на мой взгляд, единственным способом (описанным мной) - ввести виртуальный GetUnproxiedType.

Вообще тут и так косвенно все связалось с NHibernate (те же Iesi Collections), но как-то не на 100%, т.е. нет зависимостей от кода NHibernate (Iesi не является его частью).

Предположим, они хотят, чтобы Entity ни от чего стороннего не зависел; вроде бы тут только один выход - ввести этот виртуальный метод?
...
Рейтинг: 0 / 0
Общий предок для всех Entity (NHibernate) - не работает получение типа под прокси
    #37301206
OVoronov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В примере по Вашей ссылке тоже вижу на первый взгляд ошибку, что это? !GetType().IsInstanceOfType(other)) - а как же симметричность, т.е. во вторую сторону не проверяют? Является ли A экземпляром B - мало, может быть, что нет, зато B является экземпляром A.

Вообще обычно сравнивают объекты одного типа, ну или A с прокси A. Потому и не огребают проблем. (Хотя предыдущий абзац намекает, что и в этом случае огребут). А у топикстартера есть иерархия.

Второй вопрос - про Contains() и Intersect(). В нем я не специалист.
Тут на форуме кто-то уже спотыкался, вот тут у Майкрософт написано много всего, но как-то неудобно выходит, надо наследоваться от EqualityComparer<T> и потом явно передавать этот comparer внутрь словаря ... фууу...

We recommend that you derive from the EqualityComparer<T> class instead of implementing the IEqualityComparer<T> interface, because the EqualityComparer<T> class tests for equality using the IEquatable<T>.Equals method instead of the Object.Equals method. This is consistent with the Contains, IndexOf, LastIndexOf, and Remove methods of the Dictionary<TKey, TValue> class and other generic collections.
...
Рейтинг: 0 / 0
Общий предок для всех Entity (NHibernate) - не работает получение типа под прокси
    #37301755
SolYUtor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
OVoronovВ примере по Вашей ссылке тоже вижу на первый взгляд ошибку, что это? !GetType().IsInstanceOfType(other)) - а как же симметричность, т.е. во вторую сторону не проверяют? Является ли A экземпляром B - мало, может быть, что нет, зато B является экземпляром A.Вообще обычно сравнивают объекты одного типа, ну или A с прокси A. Потому и не огребают проблем. (Хотя предыдущий абзац намекает, что и в этом случае огребут). А у топикстартера есть иерархия.

Как водится, я привёл один из вариантов. !GetType().IsInstanceOfType(other)) лишь проверяет, что объекты однотипны, и не проверяет наследование. Вам решать эквивалентен ли наследник предку. Нет так сложно заменить на IsAssignableFrom, да и разрулить ситуацию с прокси - пара строчек.

OVoronovВторой вопрос - про Contains() и Intersect(). В нем я не специалист.
Тут на форуме кто-то уже спотыкался, вот тут у Майкрософт написано много всего, но как-то неудобно выходит, надо наследоваться от EqualityComparer<T> и потом явно передавать этот comparer внутрь словаря ... фууу...

Здесь соглашусь, использовать EqualityComparer<T> тут и там не очень красиво, хотя иногда это и есть решение.
...
Рейтинг: 0 / 0
Общий предок для всех Entity (NHibernate) - не работает получение типа под прокси
    #37302594
OVoronov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Лучше всего, я думаю, гарантировать проверку по Contains и Intersect через наши критерии, т.е. что предок эквивалентен потомку, и т.п. Т.о., приходим к тому, что как-то надо вызывать наше Equals из Contains. Как это сделать проще всего?


А что предок эквивалентен потомку, как насчет такого:

иерархия A->B, A->C, в объекте D есть коллекция предков - объектов A (для общности). Хотя реально туда добавляются объекты либо B, либо С, т.е. потомки. Естественно, что тогда A надо считать равным B. (При одинаковом id).

Если кому не нравится пример со смешиванием B и C в одной коллекции, то можно его видоизменить:
пусть от объекта D происходят объекты Db и Dc, у объекта D есть коллекция элементов A, но реально элементы добавляются не через объект D, а через его реализации Db и Dc: Db имеет всегда коллекцию элементов типа B, а Dc имеет коллекцию C. Логично было вынести коллекцию в общий предок объектов Db и Dc, соответственно это не коллекция B или С, а коллекция их общих предков же.
...
Рейтинг: 0 / 0
Общий предок для всех Entity (NHibernate) - не работает получение типа под прокси
    #37303743
NHibernate_User_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день!
Так в чем сошлись - подходит ли нам лучше всего виртуальный метод GetUnproxType, или как? Требования у нас такие:
а) Никакой зависимости у сборки с Entities от NHibernate
б) Прокси требуется учитывать, и иерархию тоже. Т.е. все эти объекты должны иметь одинаковое значение при одинаковом ненулевом id: A, proxy A, B:A, proxy B, C:B, proxy C.
в) Коллекции должны быть, proxy и lazyload использоваться и работать, и связи М:М тоже.

На данный момент невыясненными остаются вопросы:
- Как лучше реализовать Equals(), чтобы оно удовлетворяло всем вышеуказанным требованиям
- Как гарантировать работу Contains() и Ко. с учетом их же.
...
Рейтинг: 0 / 0
Общий предок для всех Entity (NHibernate) - не работает получение типа под прокси
    #37304008
NHibernate_User_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вот здесь чувак в 3-ем посте (т.е. во 2-м ответе) почему-то тоже утверждает, что GetType() будет работать как unproxy, и что он это использует. С чего они все так считают?
Код: plaintext
1.
2.
3.
public virtual Type GetTypeUnproxied()
 {
    return GetType();
}

Я сейчас перечитал материал и засомневался даже в коде, который делает загрузку сущностей предка (которые на самом деле являются экземплярами потомков). Вот наш пример. Тут все правильно? (от A происходит потомок B)
Код: plaintext
1.
2.
3.
4.
// получаем переменную a из поля (с типом A) какой-то entity.
A concreteA = a.GetConcrete(); // метод возвращает this
if (concreteA is B)
  Do.Some.Work(concreteA as B);

С другой стороны, некий Михельсон ( Diego Mijelshon ) пишет, что метод, возвращающий this, вообще является проблемой по трем пунктам:
1. Это "задняя дверь" к объекту, лежащему внутри. На самом деле им должен управлять NH.
2. Можно использовать это только для доступа к свойствам унаследованного класса. Для поведения надо юзать полиморфизм.
3. Никогда не надо передавать этот (полученный по this) объект в методы типа Update или Delete.

Кстати, вопрос, если вместо GetUnproxiedType() мы сделаем для каждой сущности (а не только для полиморфных, как выше) метод GetConcrete(), возвращающий this, и будем дергать его из Equals() - не приведет ли его вызов к полной загрузке всех коллекций (даже если они с lazyload)?
А если сделаем метод GetUnproxiedType(), возвращающий конкретный Type, не будет ли он возвращать A вместо B? Т.е. вызовется его реализация для предка A, т.к. NHibernate вернет при загрузке поля типа A (см. выше) именно прокси типа A?
...
Рейтинг: 0 / 0
Общий предок для всех Entity (NHibernate) - не работает получение типа под прокси
    #37304048
SolYUtor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NHibernate_User_Добрый день!
Так в чем сошлись - подходит ли нам лучше всего виртуальный метод GetUnproxType, или как? Требования у нас такие:
а) Никакой зависимости у сборки с Entities от NHibernate
б) Прокси требуется учитывать, и иерархию тоже. Т.е. все эти объекты должны иметь одинаковое значение при одинаковом ненулевом id: A, proxy A, B:A, proxy B, C:B, proxy C.
в) Коллекции должны быть, proxy и lazyload использоваться и работать, и связи М:М тоже.

На данный момент невыясненными остаются вопросы:
- Как лучше реализовать Equals(), чтобы оно удовлетворяло всем вышеуказанным требованиям
- Как гарантировать работу Contains() и Ко. с учетом их же.

Попробуйте такой класс, сделанный на основе приведённого мною выше. На абсолютную правильность не тестировал, но надеюсь идея будет понятна.

Код: 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.
namespace uNhAddIns.Entities
{
        public abstract class AbstractEntity<TIdentity> : IGenericEntity<TIdentity>
        {

                public virtual TIdentity Id { get; protected set; }


        public override bool Equals(IGenericEntity<long> other)
        {
            if (null == other) return false;

            if (ReferenceEquals(this, other))
            {
                return true;
            }

            var thisType = GetType();
            var otherType = other.GetType();

            if (thisType.IsAssignableFrom(otherType) || otherType.IsAssignableFrom(thisType))
            {
                bool otherIsTransient = Equals(other.Id, default(Int64));
                bool thisIsTransient = IsTransient();
                if (otherIsTransient || thisIsTransient)
                {
                    return false;
                }
                return other.Id.Equals(Id);
            }
            return false;
        }



                protected bool IsTransient()
                {
                        return Equals(Id, default(TIdentity));
                }

                public override bool Equals(object obj)
                {
                        var that = obj as IGenericEntity<TIdentity>;
                        return Equals(that);
                }

                public override int GetHashCode()
                {
                        return  IsTransient() ? base.GetHashCode() : Id.GetHashCode();
                }
        }
}
...
Рейтинг: 0 / 0
Общий предок для всех Entity (NHibernate) - не работает получение типа под прокси
    #37304678
NHibernate_User_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо, попробуем.
Но на вид other.GetType() невиртуально?

Самое смешное, что автор NH утверждает, что данный пример будет работать, и вот почему:

"If you don't understand how the proxy frameworks work, the idea can seem magical.

When NHibernate returns a proxy for the purposes of lazy loading, it returns a proxy instance inherited from the actual type. There are a few members we can access without forcing a load from the database. Among these are proxy's Id property or field, GetType(), and in some circumstances Equals() and GetHashCode(). Accessing any other member will force a load from the database.

When that happens, the proxy creates an internal instance. So, for example, a lazy loaded instance of Customer (CustomerProxy102987098721340978), when loaded, will internally create a new Customer instance with all of the data from the database. The proxy then does something like this:
Код: plaintext
1.
public overrides string Name {     get {        return _loadedInstance.Name;     }
  set { _loadedInstance.Name = value; } }
Incidentally, it's this overriding that requires everything to be virtual on entities that allow lazy loaded.

So, all calls to the Name property on the proxy are relayed to the internal Customer instance that has the actual data.

GetUnproxiedType() takes advantage of this. A simple call to GetType() on the proxy will return typeof(CustomerProxy02139487509812340); A call to GetUnproxiedType() will be relayed to the internal customer instance, and the internal customer instance will return typeof(Customer)."

Только вот почему у нас не работает? NH 2.0 или 2.1 не так работает, как 3.0? Или дело в том, что мы переопределили Equals в самом классе (а не предке Entity), и вызываем base.Equals()? Или потому, что что-то случилось при вызове
Код: plaintext
contract = new CContract(aOrganization, cOrganization as COrganization); //(COrganization)(cOrganization.GetConcrete())
ведь через GetConcrete(), которое возвращало this, все работало.

Вдогонку вопрос, что будет с не загруженными еще коллекциями объекта, если мы для его прокси вызовем GetConcrete(), который вернет this? Или они будут пустыми, или как? А обращение к этим коллекциям у возвращенного GetConcrete() объекта (не у прокси!) не приведет к их загрузке через LazyLoad? Как же тогда быть?
...
Рейтинг: 0 / 0
Общий предок для всех Entity (NHibernate) - не работает получение типа под прокси
    #37304792
NHibernate_User_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Фффух, по-моему, я победил этот баг, когда заменил "private Type GetUnproxiedType()" из книжки на "public virtual Type GetUnproxiedType()", все заработало (NH 2.0 or 2.1 у нас). Почему же в книжке написано "private"? Кто-то пытался пост-редактировать, скрыв ненужный вроде бы снаружи метод, и получил скрытый баг? :)

А впрочем тут и написано, что работает сей метод только под Castle Proxy, а под другими (у нас LinFu), включая свой прокси из NH 3.2, оно не работает :) лол
...
Рейтинг: 0 / 0
Общий предок для всех Entity (NHibernate) - не работает получение типа под прокси
    #37304909
NHibernate_User_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вторую проблему победил (с GetConcrete()).
LinFu - настолько кривой, что вылетали разные страшные эксепшены при попытке реализовать через дженерики.

(type argument 'T' violates the constraint of type parameter,
Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true)

Кончил тем, что

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
    public abstract class Entity<TId>
    {
        public virtual object GetConcrete()
        {
            return this;
        }
    }

cOrganization.GetConcrete() is COrganization // использование
cOrganization.GetConcrete() as COrganization // использование

Как вам такое решение? У меня под LinFu благополучно распроксирует, и Lazy коллекции не портятся, а в БД идут запросы на них, когда в отладчике просматриваю и к ним обращаюсь.
...
Рейтинг: 0 / 0
Общий предок для всех Entity (NHibernate) - не работает получение типа под прокси
    #37304937
NHibernate_User_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Третий и последный затык, только он вроде и остался нерешенным - это как удобно и элегантно перегрузить default comparer для dictionary, чтоб без боязни вызывать Contains(), Intersects(). (И для Iesi.Iset, видимо, тоже можно вызвать Contains).

Помнится, NHibernate что-то там гарантировал, какую-то там гарантированную эквивалентность двух объектов в памяти, если они соответствуют одной и той же записи в БД, или это не так? Может, он и для Contains это гарантирует, нет?
...
Рейтинг: 0 / 0
Общий предок для всех Entity (NHibernate) - не работает получение типа под прокси
    #37304950
NHibernate_User_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сейчас проверил - оч. странно - прочитал прокси из базы, а также в памяти создал совершенно новый объект с разными полями, но с тем же Id - так и чтение по ключу из словаря, и Contains для созданного List() работают правильно, оставляю все то же, меняю только id в отладчике - все опять верно, entity начинают не содержаться ни в словаре, ни в списке. Но почему отладчик не входит по дебагу в Equals??? И почему он все же учитывает именно его???
...
Рейтинг: 0 / 0
17 сообщений из 17, страница 1 из 1
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / Общий предок для всех Entity (NHibernate) - не работает получение типа под прокси
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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