使用 Breeze,在创建实体时填充 GUID 键的最简单方法是什么?
2 回答
我假设您的实体已配置为客户端负责为新实体设置 Guid 键。这是 Entity Framework Code First 实体的 Guid 键的默认值;就好像关键的财产被装饰了[DatabaseGenerated(DatabaseGeneratedOption.None)]
显而易见的方法是在创建实体之后并将其添加到管理器之前设置密钥,例如:
函数 createFoo() { var foo = fooType.createEntity(); foo.id(breeze.core.getUuid()); // 敲除实现 manager.addEntity(foo); }
这可能就是您所需要的。
另一方面,您可能会发现您在许多地方创建了新的Foos,并且由于某些奇怪的原因您无法使用该createFoo
功能。您当然不想重复该代码。
您可以使用 id-setting 行为扩展Foo
实体类型,之后您可以编写:
函数 createFoo() { var foo = fooType.createEntity(); // foo.id 为你设置 manager.addEntity(foo); }
有两种方法需要考虑 - 自定义构造函数和类型初始化器;两者都在“扩展实体”中进行了描述
构造函数
您可以在自定义构造函数中初始化密钥。Breeze 在您创建实体和实现查询的实体时都会调用构造函数。Breeze 在具体化时会替换初始键值。
这是一个假设 Knockout 模型库的示例。
函数 Foo() { foo.id(breeze.core.getUuid()); // 使用 KO } // 获取 MetadataStore 的一种方法 var store = manager.metadataStore; // 使用 Foo 类型注册 ctor store.registerEntityTypeCtor("Foo", Foo);
很简单。唯一的缺点是 Breeze 每次创建实体时都会生成一个 Guid,无论是创建一个新实体还是从查询中实现一个实体。在物化过程中浪费了精力,但那又怎样?好吧,我想这可能会成为一个性能问题,尽管在我测量之前我不会这么认为。
初始化器
假设您测量并且重复的 Guid 生成是一个严重的问题(真的吗?)。您可以改为在类型初始化程序中设置键,并且仅在创建新实体时调用 Guid 生成器。
在实体被创建或从查询中具体化之后,在将该实体返回到应用程序之前,Breeze 调用类型初始化器。显然,您不想覆盖数据库中的具体化键,因此您将在分配它之前测试键值以确保它不是真实的(即确保您正在修复创建的实体)。这是一个例子。
函数 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);
假设您在所有实体上都有一个 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);
}
这样,您就不必为所有实体创建初始化程序。