我应该为 Realm 中的每个实体定义主键吗?

Posted

技术标签:

【中文标题】我应该为 Realm 中的每个实体定义主键吗?【英文标题】:Should I define the primary key for each entity in Realm? 【发布时间】:2015-11-26 03:35:54 【问题描述】:

我注意到在 Realm 中设置 PK 不是强制性的,可以省略。但在文档中指出:

为主键属性自动创建索引。

我想澄清一些问题:

1) PK 的默认值是由 Realm 定义的,如果我不自己分配的话。是哈希还是什么? (如果我不设置 PK 并调用 [MyRealmObject primaryKey] 它返回 nil

2) 如果这个隐式 PK 默认被索引?我应该担心它,因为如果它没有被索引,是否意味着它会影响这个实体的一般性能(例如,获取对象)?

3) 每次为每个RLMObject 子类定义 PK 是否是一种好习惯,或者对于 Realm 来说不是必需的,而只是依赖于 Realm 本身定义的内部实现?

【问题讨论】:

【参考方案1】:

(免责声明:我为 Realm 工作。)

是的!在 Realm 中设置主键不是强制性的,也不是必需的,这就是为什么它完全取决于开发人员和应用程序的要求来确定在其实现中是否有必要。

回答您的问题:

1) 没有默认值;您将自己的属性之一指定为主键。 primaryKey 默认返回 nil ,因为您需要自己覆盖它,以便向 Realm 指示您想将哪个属性用作主键。一些用户将整数设置为主键,但通常情况下,使用 UUID 字符串是最常见的。

2) 没有隐式主键。您必须使用[RLMObject primaryKey] 方法明确声明哪个属性是主键,然后它将被索引。 :)

3) 在我自己的(业余时间)开发经验中,我通常发现拥有主键可以更轻松地识别和处理特定对象。例如,如果您要跨线程传递对象,则可以简单地传递主键值并使用[RLMObject objectForPrimaryKey:] 重新获取对象。显然这取决于你自己的实现需求。除非您发现确实需要主键,否则您可能不应该添加主键。

例如,如果您想将 UUID 字符串设置为主键,您将添加到 RLMObject 子类中:

@interface MyObject : RLMObject

@property NSString *uuid;

@end

@implementation MyObject

+ (NSString *)primaryKey

   return @"uuid";


+ (NSDictionary *)defaultPropertyValues

   @@"uuid": [[NSUUID UUID] UUIDString];


@end

希望对你有所帮助!

附录:为了详细说明下面的一些 cmets,主键对于任何根据数据库中是否已存在具有相同键的对象来更改其功能的 Realm API 都是明确必需的。例如,+[RLMObject createOrUpdateInRealm:] 将在具有该主键的对象不存在时向数据库添加一个新的 Realm 对象,否则将简单地更新现有对象。

因此,在主键是后续逻辑的关键组件的这些情况下,它们是必需的。但是,由于这些 API 是可以在 Realm 中添加/更新数据的不同方式的子集,因此如果您选择不使用它们,您仍然不需要拥有主键。

【讨论】:

谢谢蒂姆。还发现如果尝试执行addOrUpdateObject:方法,没有PK的对象无法更新,Realm上升'RLMException', reason: 'YourClass' does not have a primary key and can not be updated' 别担心!哦!我其实并不知道。如果您没有定义主键,我认为它只是默认为每次添加对象。谢谢! 遇到了@David 发布的评论,仍然同意,我得到了同样的错误。因此,您必须设置主键,以防您需要更新对象。你的答案应该被修改吗?【参考方案2】:

这匹马已经被打死了,但我忍不住参考了 Realm 代码,如果在没有主键的情况下创建或更新 Realm 对象,则会引发异常。

+ (instancetype)createOrUpdateInRealm:(RLMRealm *)realm withValue:(id)value 
    // verify primary key
    RLMObjectSchema *schema = [self sharedSchema];
    if (!schema.primaryKeyProperty) 
        NSString *reason = [NSString stringWithFormat:@"'%@' does not have a primary key and can not be updated", schema.className];
        @throw [NSException exceptionWithName:@"RLMExecption" reason:reason userInfo:nil];
    
    return (RLMObject *)RLMCreateObjectInRealmWithValue(realm, [self className], value, true);

【讨论】:

对于这个特定的 API 调用,是的,需要一个主键属性。这是因为为了处理“创建与更新”行为,需要有一种机制来判断该对象是否已经存在于 Realm 中(否则每次调用时都会简单地添加一个新对象)。但是这个 API 并不是在 Realm 中添加/更改数据的唯一方法,如果你不使用它,你仍然不需要为你的对象模型添加主键。 :) 是的,这很有意义。谢谢@TiM。

以上是关于我应该为 Realm 中的每个实体定义主键吗?的主要内容,如果未能解决你的问题,请参考以下文章

SQL中的每一张表都必须设有主键吗

每个 MySQL 表都应该有一个自动递增的主键吗?

SQL Server CE 中的每个表都必须有一个主键吗?

SQL中的每一张表都必须设有主键吗

多对多表应该有一个主键吗?

可以使用实体框架在另一个表中调用两次作为外键的主键吗?