Бриз: Как я могу создать ключ GUID для новых объектов на клиенте?

Используя Breeze, какой самый простой способ заполнить GUID-ключ при создании объекта?

Ответ 1

Я предполагаю, что ваш объект настроен таким образом, что клиент отвечает за установку ключа Guid для новых объектов. Это значение по умолчанию для ключа Guid элемента Entity Framework Code First; это как если бы свойство ключа было украшено [DatabaseGenerated(DatabaseGeneratedOption.None)]

Очевидным подходом является установка ключа после создания объекта и перед добавлением его в диспетчер, например:

function createFoo() {
    var foo = fooType.createEntity(); 
    foo.id(breeze.core.getUuid()); // Knockout implementation
    manager.addEntity(foo);
}

Это может быть все, что вам когда-либо понадобится.

С другой стороны, вы можете обнаружить, что во многих местах вы создаете новые Foos, и по какой-то странной причине вы не можете использовать функцию createFoo. Вы, конечно, не хотите повторять этот код.

Вы можете расширить тип сущности Foo с помощью поведения установки идентификатора, после которого вы сможете написать:

function createFoo() {
    var foo = fooType.createEntity(); // foo.id is set for you
    manager.addEntity(foo);
}

Есть два подхода к рассмотрению: пользовательский конструктор и инициализатор типа; оба описаны в " Расширение сущностей"

Конструктор

Вы можете инициализировать ключ внутри настраиваемого конструктора. Бриз вызывает конструктор как при создании объекта, так и при его материализации запрашиваемого объекта. Breeze заменит начальное значение ключа при материализации.

Вот пример, который предполагает библиотеку моделей Knockout.

function Foo() {
    foo.id(breeze.core.getUuid()); // using KO
}

// one way to get the MetadataStore
var store = manager.metadataStore;
// register the ctor with the Foo type
store.registerEntityTypeCtor("Foo", Foo);

Довольно просто. Единственным недостатком является то, что Breeze будет генерировать Guid каждый раз, когда он создает сущность, независимо от того, создает ли она новую или материализует ее из запроса. Он потратил впустую усилия во время материализации, но что? Ну, я полагаю, это может стать проблемой производительности, хотя я бы не предполагал, пока не измерил ее.

Initializer

Предположим, вы измерили, и повторное генерация Guid - серьезная проблема (действительно?). Вместо этого вы можете установить ключ в инициализаторе типа и вызвать генератор Guid только при создании нового объекта.

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

function fooInitializer(foo) {
    var emptyGuid = "00000000-0000-0000-0000-000000000000";
    if (foo.id() !=== emptyGuid) {
        foo.id(breeze.core.getUuid());
    }
}

var store = manager.metadataStore;
// register the initializer; no ctor in this example
store.registerEntityTypeCtor("Foo", function(){}, fooInitializer);

Ответ 2

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

function createInstance(breezeEntityManager, typeName) {
    var keyProperty = breezeEntityManager.metadataStore.getEntityType(typeName, false).dataProperties.filter(function (p) {
        return p.isPartOfKey;
    })[0];
    var config = {};
    config[keyProperty.name] = breeze.core.getUuid();
    return breezeEntityManager.createEntity(typeName, config);
}

Таким образом, вам не нужно будет создавать инициализатор для всех ваших объектов.