Почему моя сущность бриза не присоединяется к списку дочерних объектов?

На этот раз у меня вопрос по пустякам :)

Почему ветерок не соединяет связанные объекты. Соответствующие данные возвращаются методом репозитория на сервере. Вы видите, что из моих данных скрипача клиент получает данные.

Насколько я понимаю, вам не нужно вручную вызывать метод «расширить» в запросе на стороне клиента, если данные возвращаются с сервера.

Объектные отношения

1) Элемент может иметь много Единиц 2) Единица может относиться ко многим Элементам

Скопировано из документации Breezejs.com

Исключение свойств навигации Иногда требуется исключить свойство навигации на одной стороне ассоциации. Например, у вас может быть Person.Gender, но вам не нужен Gender.Persons; нет веских причин для перехода от гендерной сущности «Мужской» ко всем лицам мужского пола и нет причин нести накладные расходы на обновление наблюдаемого массива для этой навигации. К счастью, вы можете опустить свойство навигации на главной стороне ассоциации. Пол является основным в этом примере, поэтому вы можете опустить Gender.Persons.

--СТРУКТУРА ТАБЛИЦ БД

   CREATE TABLE [dbo].[Item](
 [Id] [int] IDENTITY(1,1) NOT NULL,
 [Name] [varchar](50) NOT NULL,
 [DisplayOrder] [int] NOT NULL
    )

   CREATE TABLE [dbo].[Unit](
 [Id] [int] IDENTITY(1,1) NOT NULL,
 [Acronym] [varchar](10) NULL,
 [Name] [varchar](50) NULL,
 [DisplayOrder] [int] NULL
     )

    CREATE TABLE [dbo].[AvailableUnit](
  [ItemId] [int] NOT NULL,
  [UnitId] [int] NOT NULL,
    CONSTRAINT [PK_AvailableUnit] PRIMARY KEY CLUSTERED 
    ([ItemId] ASC,[UnitId] ASC
     )

-- Карты EF 6

  public class ItemMap : EntityTypeConfiguration<Item> {

    public ItemMap ( ) {
        ToTable( "Item" );
        HasKey( k => new {  k.Id } );

        Property( p => p.Id ).HasColumnName( "Id" );
        Property( p => p.Name ).HasColumnName( "Name" ).HasMaxLength( 50 );
        Property( p => p.DisplayOrder ).HasColumnName( "DisplayOrder" );

        HasMany( t => t.Units )
            .WithMany( )
            .Map( m => {
                      m.ToTable( "AvailableUnit" );
                      m.MapLeftKey( "ItemId" );
                      m.MapRightKey( "UnitId" );
                  } );
     }

  }

public class UnitMap : EntityTypeConfiguration<Unit> {
    public UnitMap( ) {
        ToTable( "Unit" );
        HasKey( k => new { k.Id } );
        Property( p => p.Id ).HasColumnName( "Id" );
        Property( p => p.Acronym ).HasColumnName( "Acronym"   ).HasMaxLength(10).IsRequired();
        Property( p => p.Name ).HasColumnName( "Name" ).HasMaxLength( 50 );
        Property( p => p.DisplayOrder ).HasColumnName( "DisplayOrder" );
    }
} 

-- Пример класса

 public class Item {

    public int Id { get; set; }
    public string Name { get; set; }
    public int? DisplayOrder { get; set; }

    public virtual List<Unit> Units { get; set; }

    public Item( ) { }
}

public class Unit {

    public int Id { get; set; }
    public string Acronym { get; set; }
    public string Name { get; set; }
    public int? DisplayOrder { get; set; }

    public Unit() { }
}

--- Метод репозитория

    public IQueryable<Items> Items {
        get {
            return Context.Items
                .Include( i => i.Units );
        }
    }

---- JSON ОТ FIDDLER

 [
  {
    "$id": "1",
    "$type": "MyProject.Core.Item, MyProject.Core",
    "Id": 1,
    "Name": "Alprostadil",
    "Units": [
    {
       "$id": "8",
       "$type": "MyProject.Core.Unit, MyProject.Core",
       "Id": 1,
       "Acronym": "U1",
       "Name": "Unit 1",
       "DisplayOrder": 10
    },
    {
       "$id": "9",
       "$type": "MyProject.Core.Unit, MyProject.Core",
       "Id": 2,
       "Acronym": "U2",
       "Name": "Unit 2",
       "DisplayOrder": 20
  },
  {
       "$id": "10",
       "$type": "MyProject.Core.Unit, MyProject.Core",
       "Id": 3,
       "Acronym": "U3",
       "Name": "Unit 3",
       "DisplayOrder": 30
  },
  {
        "$id": "11",
        "$type": "MyProject.Core.Unit, MyProject.Core",
        "Id": 4,
        "Acronym": "U4",
        "Name": "Unit 4",
        "DisplayOrder": 40
  }
],    
  "DisplayOrder": 10
 }
]

-- Методы Hot Towel из Abstract Repository

       function _getById(entityName, id, forceRemote) {
           var self = this;
           var manager = self.manager;
           if (!forceRemote) {
            // check cache first
            var entity = manager.getEntityByKey(entityName, id);
            if (entity && !entity.isPartial) {
                self.log('Retrieved [' + entityName + '] id:' + entity.id + ' from  cache.', entity, true);
                if (entity.entityAspect.entityState.isDeleted()) {
                    entity = null; // hide session marked-for-delete
                }
                return $q.when(entity);
            }
        }

        // Hit the server
        // It was not found in cache, so let's query for it.
        return manager.fetchEntityByKey(entityName, id)
            .to$q(querySucceeded, self._queryFailed);

        function querySucceeded(data) {
            entity = data.entity;
            if (!entity) {
                self.log('Could not find [' + entityName + '] id:' + id, null, true);
                return null;
            }
            entity.isPartial = false;
            self.log('Retrieved [' + entityName + '] id ' + entity.id
                + ' from remote data source', entity, true);
            self.zStorage.save();
            return entity;
        }
    }

person GregL    schedule 04.03.2014    source источник
comment
Можете ли вы показать свой класс Unit?   -  person PW Kad    schedule 04.03.2014
comment
Да, только что добавил их :) Спасибо за внимание   -  person GregL    schedule 04.03.2014


Ответы (3)


В вашем классе Unit отсутствует свойство навигации, которое связывает его с Item. Добавьте следующее свойство в свой класс Unit:

public class Unit {

    public int Id { get; set; }
    public string Name { get; set; }
    public string Acronym { get; set; }
    public int ItemId { get; set; }
    public int? DisplayOrder { get; set; }

    public virtual Item Item { get; set; }

    public Unit( ) { }
}

Это позволит Breeze узнать, когда ваш юнит материализуется, к какому предмету он принадлежит.

Изменить

Извините, я пропустил в заголовке вопроса, где вы сказали, что Юнит был сложным типом. Сложный тип не имеет идентификатора в качестве ключа - я считаю, что вам нужно удалить идентификатор из модуля, чтобы EF определил его как сложный тип, или, по крайней мере, использовать нетрадиционный способ предоставления идентификатора.

public class Unit {

    public string Name { get; set; }
    public string Acronym { get; set; }
    public int? DisplayOrder { get; set; }

    public Unit( ) { }
}
person PW Kad    schedule 04.03.2014
comment
Вложение просто сообщает Breeze, какой тип объекта ожидать — вы всегда можете переопределить это свойство на клиенте и настроить идентификатор и ассоциацию, но это слишком много работы — из любопытства, что вас беспокоит в создании ассоциации? - person PW Kad; 04.03.2014
comment
Мне не нужно переходить из Unit -> Item. Поэтому просто хотел сохранить объект как можно более чистым. Есть некоторая документация с сайта бриза, которую я вставил в свой вопрос. Как вы думаете? - person GregL; 04.03.2014
comment
В тексте, на который вы ссылаетесь, говорится, что вы можете опустить ассоциацию Unit.Item, а не наоборот. - person PW Kad; 04.03.2014
comment
Можете показать обновленные модели? Вот дерьмо Действительно ли ваши метаданные показывают, что Unit является сложным типом? Я полностью пропустил это из названия вопроса... - person PW Kad; 04.03.2014
comment
Также добавлена ​​структура таблицы. Изменена нецензурная лексика в заголовке :) - person GregL; 04.03.2014

GregL, Одна сторона отношения «один ко многим» является основной стороной, описанной в документации Breeze. Итак, если вы сравните свою модель данных с примером, используемым в документации Breeze, Item ‹==> Person, Unit ‹==> Gender. Таким образом, вы хотите опустить другую сторону отношения, с которой, как я думаю, Breeze не справится, потому что ему требуется либо свойство внешнего ключа, либо свойство навигации на стороне типа «многие», чтобы знать, как связать его с «одним». "боковой тип. Имея всего лишь набор модулей, он не знает, какое свойство этих объектов использовать для формирования связи с элементом.

person Brian Noyes    schedule 04.03.2014
comment
Привет Брайан! Большое спасибо за ответ. Пытался заставить это работать весь день. Как лучше всего реализовать корневой объект со списком выбранных значений поиска. Итак, насколько я понимаю, мне нужно иметь свойства навигации как для элемента, так и для устройства? - person GregL; 05.03.2014
comment
Я переместил определение БД и объекты сопоставления EF в начало вопроса, чтобы упростить чтение важных частей. Я ошибаюсь, думая, что Бриз поддержит эту структуру? - person GregL; 05.03.2014

Моя очередь :-)

  • Item и Unit — это два обычных класса сущностей, сопоставленных с отдельными таблицами базы данных.

  • Следовательно, Unit не является сложным типом, и это не проблема.

  • Вы забыли вызвать таблицу «AvailableUnit», которая реализует реляционную ассоциацию «многие ко многим» между Item и Unit.

    HasMany( t => t.Units )
        .WithMany( )
        .Map( m => {
                  m.ToTable( "AvailableUnit" );
                  m.MapLeftKey( "ItemId" );
                  m.MapRightKey( "UnitId" );
              } );
    
  • Breeze не поддерживает ассоциации "многие ко многим". Запрос функции получил много голосов в нашем голос пользователя. Добавьте свой голос.

  • Вы можете (как вы обнаружили) отправить соответствующие Units с сервера клиенту в полезной нагрузке. Вложенные Units находятся в кеше... вы можете найти их там. Но Breeze не будет заполнять массив Item.Units за вас и не будет его поддерживать. Эти задачи ложатся на вас.

  • Мы давно рекомендовали другой подход. Мы просим вас представить сопоставление/ссылку как независимую сущность, такую ​​как AvailableUnit. Тогда вы сможете пройти путь Item.AvailableUnit.Unit.

  • Вам придется управлять ссылочными объектами (AvailableUnit) самостоятельно. В документации Breeze описан один из способов отображения и управления сценариями "многие ко многим", определяется таким образом.

Я подозреваю, что это не тот ответ, который вы хотите услышать. Так оно и есть.

person Ward    schedule 05.03.2014
comment
Всем спасибо за ответы, очень приятно!!! Независимо от ответа :)... Я не против изменить свои сущности, чтобы соответствовать бризу. Я приму удар за остальные преимущества, предлагаемые бризом. Мне действительно просто нужно сохранить список выбранных элементов из списка значений поиска. Так что если это так сейчас, то так оно и есть. Спасибо, я не видел этот образец, но сегодня вечером изучу его и поставлю свой голос :) - person GregL; 05.03.2014
comment
Каков ваш каркас для UX. Нарисуйте его на салфетке. Опишите это. Используйте это. Тогда мы сможем поговорить. - person Ward; 05.03.2014
comment
Итак, вот скрипач из предыдущего вопроса, который я разместил. Это UX, связанный с этим вопросом (вариант использования находится в верхней части скрипача). Демонстрация пользовательского интерфейса - person GregL; 05.03.2014
comment
Привет, Уорд, мне очень любопытно узнать, почему вы говорите, что отношения «многие ко многим» плохи в EF. Я всегда выполнял такие требования к данным. Если есть лучший способ .. ПОЖАЛУЙСТА, поделитесь :) Проверьте мой скрипач в комментарии выше. Чтобы увидеть, что я должен сделать. - person GregL; 06.03.2014
comment
Короче говоря, ассоциация EF «многие ко многим» почти неизбежно влечет за собой потребность в другом свойстве (isActive, linkCreatedDate, tenantId), которое мгновенно разрушает ловкость рук, которая является EF m-to-m. Вы должны вернуться к шаблону с тремя сущностями, который, как я говорю, вы должны были написать в первую очередь. За исключением того, что теперь это сложно модифицировать, у вас нет времени или бюджета, поэтому вы добавляете какой-то хак, чтобы хранить необходимую информацию в другом месте. Наступает веселье. Это бомба замедленного действия. - person Ward; 07.03.2014
comment
Кажется, я понимаю, к чему ты клонишь. Итак, вы говорите, что схема БД в порядке, но объектная модель должна иметь третий объект. Чтобы справиться с любыми потенциальными изменениями, которые могут произойти. Например: если кто-то говорит, что нам нужно знать, кто изменил список единиц для элемента 1. Теперь необходимо добавить столбец ModifiedBy, и у меня есть проблема, зависящая от степени детализации измененного отслеживания, которое им требуется. - person GregL; 07.03.2014