powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / Можно ли избавиться от Iesi.Collections, нужных для Set в NHibernate?
17 сообщений из 17, страница 1 из 1
Можно ли избавиться от Iesi.Collections, нужных для Set в NHibernate?
    #37281405
NHibernate_User_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Можно ли избавиться от Iesi.Collections, нужных для Set в NHibernate?

Собственно, коллекции для отображения двусторонних связей (как написано в NHibernate CookBook) могут быть либо Set, либо Bag.

Bag для нас не годится, т.к. делает лишние Insert и Delete при любом изменении коллекции.

Set для нас не годится, т.к. для его использования нужна сторонняя библиотека Iesi.Collections, т.о. сборка, в которой у нас лежат Entities, становится зависимой от NHibernate, использует его библиотеки.

Как быть?
...
Рейтинг: 0 / 0
Можно ли избавиться от Iesi.Collections, нужных для Set в NHibernate?
    #37281447
SolYUtor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NHibernate_User_,

set, bag и list - не просто какие-то коллекции, они несут еще и логический смысл. Без iesi.collection обойтись можно, но с дополнительными телодвижениями. Рецепт .
...
Рейтинг: 0 / 0
Можно ли избавиться от Iesi.Collections, нужных для Set в NHibernate?
    #37281452
NHibernate_User_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
С другой стороны, пример использования обычно выглядит так
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
public class Order
{
  public Order()
  {
    _items = new HashedSet<OrderItem>();
  }
  private ISet<OrderItem> _items;
  public virtual IEnumerable<OrderItem> Items
  {
    get
    {
      return _items;
    }
  }
С одной стороны, опять получается (см. мой параллельный топик ), что сторонние пользователи могут вроде бы менять коллекцию. Не знаю, есть ли в Iesi решение типа .AsReadOnly() для IList.

C другой, непонятно, из какого неймспейса брать ISet? Есть в стандартных коллекциях .NET ISet, и я, честно говоря, сначала думал, что имели в виду его. Потом в других источниках писали про Iesi.Collections.ISet. Но оказалось, что он не использует параметры. Потом я нашел Iesi.Collections.Generic.ISet. Может быть, надо его?

Далее, предположим, в коде самой Entity надо принять IEnumerable<OrderItem> и этими значениями заполнить коллекцию HashedSet. Можно ли это сделать одной строчкой, не прибегая к foreach?

Вроде есть конструктор public HashedSet(ICollection<T> initialValues);
и ICollection вроде как стандартная .NET?
...
Рейтинг: 0 / 0
Можно ли избавиться от Iesi.Collections, нужных для Set в NHibernate?
    #37281484
SolYUtor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NHibernate_User_,

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
public class Order
{
  public Order()
  {
    _items = new HashedSet<OrderItem>();
  }
  private ISet<OrderItem> _items;
  public virtual IEnumerable<OrderItem> Items
  {
    get
    {
      return new ImmutableSet<OrderItem>_items;
    }
  }

Для добавления одной строчкой в интерфейсе Iesi.Collection.Generic.Iset есть метод AddAll. Или сами напишите метод расширения.
...
Рейтинг: 0 / 0
Можно ли избавиться от Iesi.Collections, нужных для Set в NHibernate?
    #37282206
NHibernate_User_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо, будем пробовать.
Странно, вчера такая строчка не работала:
Код: plaintext
storages = new HashedSet<Storage>((ICollection<Storage>)newStorageList);
а сегодня работает.
...
Рейтинг: 0 / 0
Можно ли избавиться от Iesi.Collections, нужных для Set в NHibernate?
    #37282603
NHibernate_User_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Со строчкой разобрались, туда передавалась Ordered Enumerable, которая не умеет конвертироваться в интерфейс ICollection, хотя грустно, конечно, что если мы хотим принимать и Ordered, то одной строчкой не обойтись.
...
Рейтинг: 0 / 0
Можно ли избавиться от Iesi.Collections, нужных для Set в NHibernate?
    #37282697
SolYUtor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NHibernate_User_Спасибо, будем пробовать.
Странно, вчера такая строчка не работала:
Код: plaintext
storages = new HashedSet<Storage>((ICollection<Storage>)newStorageList);
а сегодня работает.

Опять хотите обмануть хибер, подменив ему коллекцию?
...
Рейтинг: 0 / 0
Можно ли избавиться от Iesi.Collections, нужных для Set в NHibernate?
    #37283230
NHibernate_User_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Просто так часто делают в Шарпе.

А что, надо сначала коллекцию очистить, а потом писать туда элементы?
Код: plaintext
1.
2.
            storages.Clear; //= new HashedSet<Storage>();
            storages.AddAll((ICollection<Storage>)newStorageList);

Теперь проблема стоит в том, что другие entity напрямую пишут в коллекцию данного entity. По-хорошему, реализацию бы сделать protected internal. Выкрутились тремя (!) полями: одним для паблика (отдает рид-онли коллекцию), другой для entity (отдает не рид-онли коллекцию), и третий для NH.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
        public virtual IEnumerable<AccountOrganization> AccountOrganizations
        {
            get { return new ImmutableSet<AccountOrganization>(accountOrganizations); }
        }
        private Iesi.Collections.Generic.ISet<AccountOrganization> _accountOrganizations; // NH
        protected internal virtual Iesi.Collections.Generic.ISet<AccountOrganization> accountOrganizations // entities
        {
            get { return _accountOrganizations; }
        }
Заставить NH обратиться к свойству AccountOrganizations на чтение, а к свойству (не полю!) accountOrganizations на запись (тогда в нем стояло просто { get; set; }) я не смог. :(

Без protected internal скрытое поле не видят другие entity, затем без virtual и {get;set;} на него ругается NH, а потом все равно не может его найти, я уж пробовал и ReadOnlyPropertyThroughCamelCaseField, не вышло.

маппинг:
Код: plaintext
1.
2.
3.
4.
5.
            HasManyToMany(x => x.AccountOrganizations)
                .AsSet().Access.CamelCaseField(Prefix.Underscore) /////
                .Table("AccountOrganizationStorage")
                .ParentKeyColumn("StorageId")
                .ChildKeyColumn("AccountOrganizationId").Cascade.All();

Как-то надо избавиться от трех полей... Очень прошу помочь!
...
Рейтинг: 0 / 0
Можно ли избавиться от Iesi.Collections, нужных для Set в NHibernate?
    #37283337
SolYUtor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NHibernate_User_Просто так часто делают в Шарпе.

А что, надо сначала коллекцию очистить, а потом писать туда элементы?
Код: plaintext
1.
2.
            storages.Clear; //= new HashedSet<Storage>();
            storages.AddAll((ICollection<Storage>)newStorageList);

Да. коллекцию иницилизируете только в конструкторе, и больше никогда и нигде не переписывайте это поле.
NHibernate_User_Теперь проблема стоит в том, что другие entity напрямую пишут в коллекцию данного entity. По-хорошему, реализацию бы сделать protected internal. Выкрутились тремя (!) полями: одним для паблика (отдает рид-онли коллекцию), другой для entity (отдает не рид-онли коллекцию), и третий для NH.

Мысль в корне неправильная. Доступ к коллекции надо инкапсулировать, дабы никто не менял состояние класса. Это даже не проблема хибера, а проблема дизайна. Если желаете себе добра - не давайте менять коллекцию напрямую. Не так трудно написать два метода AddStorage/RemoveStorage. Буквы экономит?

NHibernate_User_Заставить NH обратиться к свойству AccountOrganizations на чтение, а к свойству (не полю!) accountOrganizations на запись (тогда в нем стояло просто { get; set; }) я не смог. :(

Без protected internal скрытое поле не видят другие entity, затем без virtual и {get;set;} на него ругается NH, а потом все равно не может его найти, я уж пробовал и ReadOnlyPropertyThroughCamelCaseField, не вышло.

маппинг:
Код: plaintext
1.
2.
3.
4.
5.
            HasManyToMany(x => x.AccountOrganizations)
                .AsSet().Access.CamelCaseField(Prefix.Underscore) /////
                .Table("AccountOrganizationStorage")
                .ParentKeyColumn("StorageId")
                .ChildKeyColumn("AccountOrganizationId").Cascade.All();

Как-то надо избавиться от трех полей... Очень прошу помочь!

Пусть хибер работает напрямую с полем. Ваша стратегия именования называется camelcase.underscore. Не знаю, есть ли такое во флюенте. В общем бест-практис для хибера должен выглдять так:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
public class Order
{
  public Order()
  {
    _items = new HashedSet<OrderItem>();
  }
  private ISet<OrderItem> _items;
  public virtual IEnumerable<OrderItem> Items
  {
    get
    {
      return new ImmutableSet<OrderItem>_items;
    }
  }
  public virtual void AddOrderItem(OrderItem item)
  {
     _items.Add(item);
  }
  public virtual void RemoveOrderItem(OrderItem item)
  {
     _items.Remove(item);
  }
}
...
Рейтинг: 0 / 0
Можно ли избавиться от Iesi.Collections, нужных для Set в NHibernate?
    #37284962
NHibernate_User_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Беда в том, что у нас связь М:М и, следовательно, есть 2 коллекции, которые нужно синхронно обновлять.

Т.е. при вызове метода X.DeleteY(y) надо убрать элемент из коллекции x.Y и Y.x,
и при вызове метода Y.DeleteX(x) тоже.

Если сделать не через коллекцию, то произойдет зацикливание.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
class X
{
  list <Y> Y;
  DeleteY(Y y)
  {
    Y.remove(y);
    y.DeleteX(this);
  }
}

class Y
{
  list <X> X;
  DeleteX(X x)
  {
    X.remove(x);
    x.DeleteY(this);
  }
}

Мы вроде смотрели во всех блогах, ресурсах по DDD - все делают именно так. Однако как это сделать с NH, похоже, непонятно :(
...
Рейтинг: 0 / 0
Можно ли избавиться от Iesi.Collections, нужных для Set в NHibernate?
    #37285166
NHibernate_User_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Короче говоря, если у Вас в проектах были связи Many-To-Many, то как Вы решали проблему с удалением связи из Entity? Как выглядели методы и как выглядели маппинги?
...
Рейтинг: 0 / 0
Можно ли избавиться от Iesi.Collections, нужных для Set в NHibernate?
    #37285286
NHibernate_User_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Можно ведь нагородить огород с Add и Delete, но тогда придется 4 метода удаления делать, а не 2, как сейчас и как хотелось бы: а) в объекте Y метод удаляет X из Y (из обоих коллекций в обоих объектах); он удаляет X из "своей" коллекции, а потом вызывает б) в объекте X метод чисто для удаления объекта Y из X, не трогая парную коллекцию. Этот второй метод не должен вызываться ниоткуда, кроме как из первого - для удаления же извне надо вызывать первый метод или третий.
Третий - соответственно в объекте X удаляет Y "полностью". Вызывает четвертый, который "не полностью" удаляет только объект X из объекта Y и не трогает "парную" коллекцию.
Но так же нелепо.
...
Рейтинг: 0 / 0
Можно ли избавиться от Iesi.Collections, нужных для Set в NHibernate?
    #37286052
NHibernate_User_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В принципе, попытался замапить скрытое поле, но Fluent его не видит. Пришлось выходить из положения через Reveal.Member<> (это само по себе не идеально), но тоже не до конца работает. Почему-то поле переименовывает в маппинге в Pascal style, если найдет такое (!)

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
// маппится, а также для доступа из других entities
protected internal virtual Iesi.Collections.Generic.ISet<BigBang> bigBangs { get; set; }

        public virtual IEnumerable<BigBang> BigBangs // чисто для прочих слоев приложения
        {
            get { return new ImmutableSet<BigBang>(bigBangs ); }
            set
            {
                int y = 0; // сюда ставим брейкпойнт
                var uj = y;
            }
        }

// маппинг Fluent
            HasManyToMany<BigBang>(Reveal.Member<BigEntity>("bigBangs"))
                .AsSet() //.Access.Property()
                .Table("BigBangStorage")
                .ParentKeyColumn("StorageId")
                .ChildKeyColumn("BigBangId").Cascade.All();

// экспортящийся маппинг XML - имя (name="BigBangs") зачем-то переведено в Pascal style, т.е. первая буква
// сделана большой. Хотя было же с маленькой:bigBangs ! 

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
    <set access="property" cascade="all" name="BigBangs" table="BigBangStorage"
   mutable="true">
      <key foreign-key="PFK_BigBang_Storage">
        <column name="StorageId" />
      </key>
      <many-to-many class="..., Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
        <column name="BigBangId" />
      </many-to-many>
    </set>

Короче говоря, Fluent почему-то пытается вставить первую большую букву. Видит - два поля в классе: BigBangs и bigBangs, так почему-то ставит то, которое с большой (и public).

Но если их развести, т.е. назвать по-разному, скажем, BigBangs и bigBangsM, то Reveal.Member<BigEntity>("bigBangsM")) работает как часы и ривилит именно bigBangsM. Как с этим бороться?
...
Рейтинг: 0 / 0
Можно ли избавиться от Iesi.Collections, нужных для Set в NHibernate?
    #37286207
NHibernate_User_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В принципе, нашел пару методов: туттут описано, как смешать конфигурацию маппингов - fluent с auto). Но решили просто переименовать одну из коллекций и не заморачиваться.
...
Рейтинг: 0 / 0
Можно ли избавиться от Iesi.Collections, нужных для Set в NHibernate?
    #37286260
NHibernate_User_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Встает вопрос, не будут ли слишком большие затраты при вызове new ImmutableSet()? Мы очень обеспокоены этим... Нет ли более быстрого способа сделать коллекцию readonly?
Как работает new ImmutableSet? Много ли он выполняет операций?
...
Рейтинг: 0 / 0
Можно ли избавиться от Iesi.Collections, нужных для Set в NHibernate?
    #37288955
SolYUtor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NHibernate_User_,

Сколько букав набежало за время моего отпуска...

Давайте по порядку:

Если у вас есть двунаправленные связи - поддерживайте согласованность связи только с одной стороны. Это лишит вас
необходимости писать кучу дублирующих методов.

Что касается FH - мне не нравится его способ маппить объекты, и не использую. Поэтому как мапить конкретное поведение с его помощь - это к гуглу.

По поводу производительности ImmutableSet - не страдайте фигней. Затраты на него пренебрежимо малы по сравнению например с операциями ввода-вывода. Хотите узнать, что действительно тормозит - берите профайлер кода, и вперёд. И рекомендую прочитать про оптимизацию .
...
Рейтинг: 0 / 0
Можно ли избавиться от Iesi.Collections, нужных для Set в NHibernate?
    #37290611
NHibernate_User_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо, еще если кто ответит на соседнюю тему про Null у прокси , буду очень рад :)
...
Рейтинг: 0 / 0
17 сообщений из 17, страница 1 из 1
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / Можно ли избавиться от Iesi.Collections, нужных для Set в NHibernate?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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