将新属性添加到现有核心数据实体关系

时间:2023-01-27 10:40:02

I'm not sure if my understanding of Core Data relationships is flawed as I can't seem to achieve what I want to do.

我不确定我对核心数据关系的理解是否有缺陷,因为我似乎无法实现我想做的事情。

I have a 2 entities created to manage Chat on the app and a one-to-Many relationship between the users and the messages. So a user can have many messages but the messages have just you user (creator).

我创建了2个实体来管理应用程序上的聊天,以及用户和消息之间的一对多关系。因此,用户可以拥有许多消息,但消息只有您的用户(创建者)。

将新属性添加到现有核心数据实体关系

I am trying to update the ChatUser entity relationship when a new message is added whereby a connection between the ChatUser ID and the ChatMessage is established. I can do this but the issue arises when I go to add a new message to an existing userId. All that is currently being achieved though is adding an extra userId into ChatUser instead of adding only the relationship to the existing UserId.

我想在添加新消息时更新ChatUser实体关系,从而建立ChatUser ID和ChatMessage之间的连接。我可以这样做,但当我向现有userId添加新消息时出现问题。目前正在实现的只是在ChatUser中添加额外的userId,而不是仅添加与现有UserId的关系。

NSManagedObjectContext *context = [self managedObjectContext];
NSError *error = nil;

// 4 . Get Timestamp for Rippll
float timestamp = @([[NSDate date] timeIntervalSince1970]).floatValue;
 NSString * jayID = @"eu-west-1:be6457ce-bac1-412d-9307-e375e52e22ff";

  NSString *message = @"Science string!";

// Create a new managed object
ChatUser *chatUserManagedObject = [NSEntityDescription insertNewObjectForEntityForName:@"ChatUser" inManagedObjectContext:context];
Chat *chatManagedObject = [NSEntityDescription insertNewObjectForEntityForName:@"ChatMessage" inManagedObjectContext:context];
Timeline *timelineManagedObject = [NSEntityDescription insertNewObjectForEntityForName:@"Timeline" inManagedObjectContext:context];

// 3 . Save Timeline
[timelineManagedObject setEvent:chatEvent];
[timelineManagedObject setTimestamp:[NSNumber numberWithFloat:timestamp]];
[timelineManagedObject setMeta:@""];
[timelineManagedObject setViewed:@NO];
[timelineManagedObject setEventID:jayID];

//Save UserMessage
[chatManagedObject setChatId:jayID];
[chatManagedObject setTimestamp:[NSNumber numberWithFloat:timestamp]];
[chatManagedObject setMessage:message];
[chatManagedObject setMedia:@""];

//Check if value exists
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"ChatUser"];
[request setPredicate:[NSPredicate predicateWithFormat:@"userId = %@", jayID]];
[request setFetchLimit:1];

NSArray *entities = [[context executeFetchRequest:request error:&error] mutableCopy];

if (entities.count == 0) {

    NSLog(@"GOOD TO ADD");
        // no matching object

    [chatUserManagedObject setUserId:jayID];

    //Create Relationship
    [chatUserManagedObject addChatObject:chatManagedObject];

} else {

    NSLog(@"IT EXISTS!");

    [chatManagedObject setChat:chatUserManagedObject];

}

// Save the object to persistent store
if (![context save:&error]) {
    NSLog(@"Can't Save! %@ %@", error, [error localizedDescription]);
}

4 个解决方案

#1


3  

I thin k, @PangHoMing was on the right track, but used Magical Records. Let's do it solely with CD:

我很瘦,@ PangHoMing在正确的轨道上,但使用了Magical Records。让我们单独用CD做:

First rename the relationships. Probably in ChatMessage there should be a to-1 relationship named user (or chatUser) and in ChatUser there should be a to-N relationship messages (or chatMessages). They should be inverse relationship.

首先重命名关系。可能在ChatMessage中应该有一个名为user(或chatUser)的to-1关系,而在ChatUser中应该有一个to-N关系消息(或chatMessages)。他们应该是反向关系。

Next you should ask for the existence of a user before creating it. (Otherwise you create phantom users.) You got the code for it:

接下来,您应该在创建用户之前询问用户是否存在。 (否则你会创建幻像用户。)你得到了它的代码:

// Create message as you did
ChatMessage *message = …;
…

// The user will go here
ChatUser *user; // Do not use types in names unless conversion is subject of your code

// Look for an existing one
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"ChatUser"];
[request setPredicate:[NSPredicate predicateWithFormat:@"userId = %@", jayID]];
[request setFetchLimit:1];

NSArray *entities = [[context executeFetchRequest:request error:&error] mutableCopy];

if (entities.count == 0) 
{
  // Only if there is none, create one  
  user = [NSEntityDescription insertNewObjectForEntityForName:@"ChatUser" inManagedObjectContext:context];
  // Set-up user's properties
  …
} 
else 
{
  // Use the existing one
  user = entities[0];
}

[message setValue:user forKey:@"user"]; // message.user = user;

As mentioned by others, the inverse relationship is maintained by CD. However, you can use the inverse relationship to add the message, if this is more readable for you:

如其他人所述,反向关系由CD维持。但是,您可以使用反向关系添加消息,如果这对您更具可读性:

[[user mutableSetValueForKey:@"messages"] addObject:message]; // [user addMessagesObject:message]

This will maintain the "original" relationship, too.

这也将保持“原始”关系。

#2


6  

Core Data will automatically manage the other end of the relationship once you initiate it from either direction. You can either add to ChatUser's chat collection or set ChatMessage's chat with an instance of an NSManagedObject and that's all you have to do. Note that this process does not require you to manage foreign keys, that complexity is abstracted from you. You can still store server-side IDs if they help you interact with an API, but they are not required for Core Data.

一旦从任一方向启动,Core Data将自动管理关系的另一端。您可以添加到ChatUser的聊天集合或将ChatMessage的聊天设置为NSManagedObject的实例,这就是您所要做的。请注意,此过程不需要您管理外键,从而提取复杂性。如果它们可以帮助您与API进行交互,您仍然可以存储服务器端ID,但Core Data不需要它们。

I would recommend changing one end of the relationship so that both are not named the same thing. Consider updating ChatUser's relationship to be messages or something similar.

我建议改变关系的一端,这样两者都不会被命名为同一个东西。考虑将ChatUser的关系更新为消息或类似的东西。

#3


1  

  1. You should first check if there is an ChatUser entity already exists in your Context. Simply by trying to get the ChatUser with that userId, if there is a ChatUser return that mean that ChatUser is already been crated; if it return nil that means there isn't a ChatUser entity with that userId being created.
  2. 您应首先检查您的Context中是否已存在ChatUser实体。只需尝试使用该userId获取ChatUser,如果有ChatUser返回表示ChatUser已经被创建;如果它返回nil,则意味着没有正在创建userId的ChatUser实体。
  3. To handle 1 - many relation, you should use [message setChatUser:chatUser] instead of chatUser addMessageObject
  4. 要处理1 - 多关系,您应该使用[message setChatUser:chatUser]而不是chatUser addMessageObject

Feel free to ask any follow up question if you have any. Cheers!

如果您有任何问题,请随时提出任何跟进问题。干杯!

#4


1  

Try to implement something like this one. This solution is almost the same as proposed by Amin Negm-Awad

尝试实现类似这样的东西。该解决方案几乎与Amin Negm-Awad提出的解决方案相同

NSManagedObjectContext *context = [self managedObjectContext];
NSError *error = nil;

// 4 . Get Timestamp for Rippll

NSString * jayID = @"eu-west-1:be6457ce-bac1-412d-9307-e375e52e22ff";

NSString *message = @"Science string!";

//Check if value exists
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"ChatUser"];
[request setPredicate:[NSPredicate predicateWithFormat:@"userId = %@", jayID]];
[request setFetchLimit:1];

NSArray *entities = [[context executeFetchRequest:request error:&error] mutableCopy];

ChatUser *chatUserManagedObject = nil;

if (entities.count)
{
    NSLog(@"IT EXISTS!");
    chatUserManagedObject = entities.firstObject;
}
else
{
    NSLog(@"GOOD TO ADD");
    chatUserManagedObject = [NSEntityDescription insertNewObjectForEntityForName:@"ChatUser" inManagedObjectContext:context];
    [chatUserManagedObject setUserId:jayID];
}

// Create a new managed object

Chat *chatManagedObject = [NSEntityDescription insertNewObjectForEntityForName:@"ChatMessage" inManagedObjectContext:context];

//Save UserMessage
[chatManagedObject setChatId:jayID];
[chatManagedObject setTimestamp:[NSDate date]];
[chatManagedObject setMessage:message];
[chatManagedObject setMedia:@""];

[chatUserManagedObject addChatObject:chatManagedObject];

// Save the object to persistent store
if (![context save:&error]) {
    NSLog(@"Can't Save! %@ %@", error, [error localizedDescription]);
}

#1


3  

I thin k, @PangHoMing was on the right track, but used Magical Records. Let's do it solely with CD:

我很瘦,@ PangHoMing在正确的轨道上,但使用了Magical Records。让我们单独用CD做:

First rename the relationships. Probably in ChatMessage there should be a to-1 relationship named user (or chatUser) and in ChatUser there should be a to-N relationship messages (or chatMessages). They should be inverse relationship.

首先重命名关系。可能在ChatMessage中应该有一个名为user(或chatUser)的to-1关系,而在ChatUser中应该有一个to-N关系消息(或chatMessages)。他们应该是反向关系。

Next you should ask for the existence of a user before creating it. (Otherwise you create phantom users.) You got the code for it:

接下来,您应该在创建用户之前询问用户是否存在。 (否则你会创建幻像用户。)你得到了它的代码:

// Create message as you did
ChatMessage *message = …;
…

// The user will go here
ChatUser *user; // Do not use types in names unless conversion is subject of your code

// Look for an existing one
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"ChatUser"];
[request setPredicate:[NSPredicate predicateWithFormat:@"userId = %@", jayID]];
[request setFetchLimit:1];

NSArray *entities = [[context executeFetchRequest:request error:&error] mutableCopy];

if (entities.count == 0) 
{
  // Only if there is none, create one  
  user = [NSEntityDescription insertNewObjectForEntityForName:@"ChatUser" inManagedObjectContext:context];
  // Set-up user's properties
  …
} 
else 
{
  // Use the existing one
  user = entities[0];
}

[message setValue:user forKey:@"user"]; // message.user = user;

As mentioned by others, the inverse relationship is maintained by CD. However, you can use the inverse relationship to add the message, if this is more readable for you:

如其他人所述,反向关系由CD维持。但是,您可以使用反向关系添加消息,如果这对您更具可读性:

[[user mutableSetValueForKey:@"messages"] addObject:message]; // [user addMessagesObject:message]

This will maintain the "original" relationship, too.

这也将保持“原始”关系。

#2


6  

Core Data will automatically manage the other end of the relationship once you initiate it from either direction. You can either add to ChatUser's chat collection or set ChatMessage's chat with an instance of an NSManagedObject and that's all you have to do. Note that this process does not require you to manage foreign keys, that complexity is abstracted from you. You can still store server-side IDs if they help you interact with an API, but they are not required for Core Data.

一旦从任一方向启动,Core Data将自动管理关系的另一端。您可以添加到ChatUser的聊天集合或将ChatMessage的聊天设置为NSManagedObject的实例,这就是您所要做的。请注意,此过程不需要您管理外键,从而提取复杂性。如果它们可以帮助您与API进行交互,您仍然可以存储服务器端ID,但Core Data不需要它们。

I would recommend changing one end of the relationship so that both are not named the same thing. Consider updating ChatUser's relationship to be messages or something similar.

我建议改变关系的一端,这样两者都不会被命名为同一个东西。考虑将ChatUser的关系更新为消息或类似的东西。

#3


1  

  1. You should first check if there is an ChatUser entity already exists in your Context. Simply by trying to get the ChatUser with that userId, if there is a ChatUser return that mean that ChatUser is already been crated; if it return nil that means there isn't a ChatUser entity with that userId being created.
  2. 您应首先检查您的Context中是否已存在ChatUser实体。只需尝试使用该userId获取ChatUser,如果有ChatUser返回表示ChatUser已经被创建;如果它返回nil,则意味着没有正在创建userId的ChatUser实体。
  3. To handle 1 - many relation, you should use [message setChatUser:chatUser] instead of chatUser addMessageObject
  4. 要处理1 - 多关系,您应该使用[message setChatUser:chatUser]而不是chatUser addMessageObject

Feel free to ask any follow up question if you have any. Cheers!

如果您有任何问题,请随时提出任何跟进问题。干杯!

#4


1  

Try to implement something like this one. This solution is almost the same as proposed by Amin Negm-Awad

尝试实现类似这样的东西。该解决方案几乎与Amin Negm-Awad提出的解决方案相同

NSManagedObjectContext *context = [self managedObjectContext];
NSError *error = nil;

// 4 . Get Timestamp for Rippll

NSString * jayID = @"eu-west-1:be6457ce-bac1-412d-9307-e375e52e22ff";

NSString *message = @"Science string!";

//Check if value exists
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"ChatUser"];
[request setPredicate:[NSPredicate predicateWithFormat:@"userId = %@", jayID]];
[request setFetchLimit:1];

NSArray *entities = [[context executeFetchRequest:request error:&error] mutableCopy];

ChatUser *chatUserManagedObject = nil;

if (entities.count)
{
    NSLog(@"IT EXISTS!");
    chatUserManagedObject = entities.firstObject;
}
else
{
    NSLog(@"GOOD TO ADD");
    chatUserManagedObject = [NSEntityDescription insertNewObjectForEntityForName:@"ChatUser" inManagedObjectContext:context];
    [chatUserManagedObject setUserId:jayID];
}

// Create a new managed object

Chat *chatManagedObject = [NSEntityDescription insertNewObjectForEntityForName:@"ChatMessage" inManagedObjectContext:context];

//Save UserMessage
[chatManagedObject setChatId:jayID];
[chatManagedObject setTimestamp:[NSDate date]];
[chatManagedObject setMessage:message];
[chatManagedObject setMedia:@""];

[chatUserManagedObject addChatObject:chatManagedObject];

// Save the object to persistent store
if (![context save:&error]) {
    NSLog(@"Can't Save! %@ %@", error, [error localizedDescription]);
}