问题 Breeze:如何为客户端上的新实体创建GUID密钥?


使用Breeze,在创建实体时填充GUID键的最简单方法是什么?


8839
2017-12-12 22:42


起源



答案:


我假设您的实体已配置为客户端负责为新实体设置Guid密钥。这是Entity Framework Code First实体的Guid密钥的默认值;好像关键属性是用装饰的 [DatabaseGenerated(DatabaseGeneratedOption.None)]

显而易见的方法是在创建实体之后并在将其添加到管理器之前设置密钥,例如:

function createFoo(){
    var foo = fooType.createEntity();
    foo.id(breeze.core.getUuid()); //淘汰实施
    manager.addEntity(FOO);
}

这可能就是你所需要的。

另一方面,您可能会发现您正在创建新的 FOOS 在很多地方,由于一些奇怪的原因,你不能使用 createFoo 功能。你当然不想重复那段代码。

你可以扩展 Foo 具有id设置行为的实体类型,之后您就可以编写:

function createFoo(){
    var foo = fooType.createEntity(); // foo.id是为你设置的
    manager.addEntity(FOO);
}

有两种方法需要考虑 - 自定义构造函数和类型初始值设定项;两者都在“扩展实体

构造函数

您可以在自定义构造函数中初始化密钥。 Breeze在您创建实体时以及在实现查询实体时都会调用构造函数。 Breeze将在实现时替换初始键值。

这是一个假设Knockout模型库的例子。

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

//获取MetadataStore的一种方法
var store = manager.metadataStore;
//用Foo类型注册ctor
store.registerEntityTypeCtor(“Foo”,Foo);

很简单。唯一的缺点是Breeze每次创建一个实体时都会生成一个Guid,无论是创建一个实体还是从查询中实现一个实体。在实现过程中浪费了精力,但那又如何呢?好吧,我想是的 威力 成为一个性能问题,虽然我不会这样做,直到我测量它。

初始化

假设您测量并且重复的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;
//注册初始化程序;在这个例子中没有ctor
store.registerEntityTypeCtor(“Foo”,function(){},fooInitializer);

15
2017-12-12 23:40



该 breeze.core.getUuid 上面提到的方法是一个无证的,非官方的Breeze实用程序。我认为它将成为官方......也许是以不同的名字......但我无法证实这一点。使用风险(如我所知)或复制其实施并使其成为您自己的实用程序。 - Ward
只需仔细检查:if语句上的感叹号是不是错误? - user210757


答案:


我假设您的实体已配置为客户端负责为新实体设置Guid密钥。这是Entity Framework Code First实体的Guid密钥的默认值;好像关键属性是用装饰的 [DatabaseGenerated(DatabaseGeneratedOption.None)]

显而易见的方法是在创建实体之后并在将其添加到管理器之前设置密钥,例如:

function createFoo(){
    var foo = fooType.createEntity();
    foo.id(breeze.core.getUuid()); //淘汰实施
    manager.addEntity(FOO);
}

这可能就是你所需要的。

另一方面,您可能会发现您正在创建新的 FOOS 在很多地方,由于一些奇怪的原因,你不能使用 createFoo 功能。你当然不想重复那段代码。

你可以扩展 Foo 具有id设置行为的实体类型,之后您就可以编写:

function createFoo(){
    var foo = fooType.createEntity(); // foo.id是为你设置的
    manager.addEntity(FOO);
}

有两种方法需要考虑 - 自定义构造函数和类型初始值设定项;两者都在“扩展实体

构造函数

您可以在自定义构造函数中初始化密钥。 Breeze在您创建实体时以及在实现查询实体时都会调用构造函数。 Breeze将在实现时替换初始键值。

这是一个假设Knockout模型库的例子。

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

//获取MetadataStore的一种方法
var store = manager.metadataStore;
//用Foo类型注册ctor
store.registerEntityTypeCtor(“Foo”,Foo);

很简单。唯一的缺点是Breeze每次创建一个实体时都会生成一个Guid,无论是创建一个实体还是从查询中实现一个实体。在实现过程中浪费了精力,但那又如何呢?好吧,我想是的 威力 成为一个性能问题,虽然我不会这样做,直到我测量它。

初始化

假设您测量并且重复的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;
//注册初始化程序;在这个例子中没有ctor
store.registerEntityTypeCtor(“Foo”,function(){},fooInitializer);

15
2017-12-12 23:40



该 breeze.core.getUuid 上面提到的方法是一个无证的,非官方的Breeze实用程序。我认为它将成为官方......也许是以不同的名字......但我无法证实这一点。使用风险(如我所知)或复制其实施并使其成为您自己的实用程序。 - Ward
只需仔细检查:if语句上的感叹号是不是错误? - user210757


假设您在我们的所有实体上都有一个Guid代理键,就像我们的情况一样,您可以编写一个createInstance工厂,以非常通用的方式执行以下操作:

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);
}

这样,您就不必为所有实体创建初始化程序。


1
2018-04-09 17:28