I've got a problem with empty json list mapping, I've got a JSON response that look this way :
{
id = 1;
image = "http://image.com/image.png";
name = "Test Category #1";
"restricted_position" = 0;
"restricted_time" = 0;
restrictions = {
"restricted_position_detail" = (
);
"restricted_time_detail" = (
);
}
The mapping for the class look like this :
+(RKManagedObjectMapping *)getObjectMapping
{
RKObjectRelationshipMapping *restrictionMapping = [RKObjectRelationshipMapping mappingFromKeyPath:#"restrictions" toKeyPath:#"restrictions" withMapping:[Restriction getObjectMapping]];
RKManagedObjectMapping *mapping = [RKManagedObjectMapping mappingForClass:[PLCategory class] inManagedObjectStore:[RKObjectManager sharedManager].objectStore];
[mapping mapKeyPath:#"id" toAttribute:#"identifiant"];
[mapping mapKeyPath:#"name" toAttribute:#"name"];
[mapping mapKeyPath:#"image" toAttribute:#"imageUrl"];
[mapping mapKeyPath:#"restricted_position" toAttribute:#"restricted_position"];
[mapping mapKeyPath:#"restricted_time" toAttribute:#"restricted_time"];
[mapping addRelationshipMapping:restrictionMapping];
[mapping setPrimaryKeyAttribute:#"identifiant"];
return mapping;
}
The mapping for the Restriction class :
+(RKManagedObjectMapping *)getObjectMapping
{
RKObjectRelationshipMapping *zg_mapping = [RKObjectRelationshipMapping mappingFromKeyPath:#"restricted_time_detail" toKeyPath:#"restricted_time_detail" withMapping:[GeographicalArea getObjectMapping]];
RKObjectRelationshipMapping *ph_mapping = [RKObjectRelationshipMapping mappingFromKeyPath:#"restricted_position_detail" toKeyPath:#"restricted_position_detail" withMapping:[TimeSlot getObjectMapping]];
RKManagedObjectMapping *mapping = [RKManagedObjectMapping mappingForClass:[Restriction class] inManagedObjectStore:[RKObjectManager sharedManager].objectStore];
[mapping addRelationshipMapping:zg_mapping];
[mapping addRelationshipMapping:ph_mapping];
return mapping;
}
No matter what I try I keep getting these annoying errors :
Core Data Save Error
NSLocalizedDescription: The operation couldn’t be completed. (Cocoa error 1580.)
NSValidationErrorKey: restricted_position_detail
NSValidationErrorPredicate: (null)
NSValidationErrorObject:
<Restriction: 0xb9c2f20> (entity: Restriction; id: 0xb9b5d90 <x-coredata:///Restriction/tE6CDEA6C-5A2A-48AE-9454-A8E6CC35F5078> ; data: {
category = "0xb9b67b0 <x-coredata:///PLCategory/tE6CDEA6C-5A2A-48AE-9454-A8E6CC35F5077>";
"restricted_position_detail" = (
);
"restricted_time_detail" = (
);
})
2013-07-08 12:39:00.716 [7442:28513] E restkit.core_data:RKManagedObjectStore.m:263 Core Data Save Error
NSLocalizedDescription: The operation couldn’t be completed. (Cocoa error 1580.)
NSValidationErrorKey: restricted_time_detail
NSValidationErrorPredicate: (null)
NSValidationErrorObject:
<Restriction: 0xb9c2f20> (entity: Restriction; id: 0xb9b5d90 <x-coredata:///Restriction/tE6CDEA6C-5A2A-48AE-9454-A8E6CC35F5078> ; data: {
category = "0xb9b67b0 <x-coredata:///PLCategory/tE6CDEA6C-5A2A-48AE-9454-A8E6CC35F5077>";
"restricted_position_detail" = (
);
"restricted_time_detail" = (
);
})
What I'd like to do is map these empty list with an empty NSArray. Does anyone have a clue how to do that ? is it even possible ?
The problem is that you have made the relationships non-optional. By default they will be empty sets (not arrays), but if you try to save when the sets are empty you will get validation errors because you configured that the relationships have to have at least one connection (that's what non-optional means).
If you want to allow zero connections, make the relationships optional.
Note that you might wan't to make the other end of the relationships non-optional, so you know if you have a GeographicalArea or TimeSlot then it must be connected to a Restriction. This would usually tie in with a Cascade deletion rule.
Related
Having this weird issue, No matter what predicate I apply its only returning one result, and if I don't add any predicate its returns all the rows of the table, what I want is only return the rows with matching progIds
I have the list of programIds and based on that I want to search in TvInfo table.
.......
......
progId = [Int64(3211),Int64(16844)] // hardcored ids from tvInfo table
let tvInfoRequest: NSFetchRequest<TvInfo> = TvInfo.fetchRequest()
tvInfoRequest.predicate = NSPredicate(format: "progId == %i", argumentArray: progId)
tvInfoRequest.returnsDistinctResults = true
tvInfoRequest.resultType = .managedObjectResultType
var tvShows = [TvInfo]()
coreDataStack.managedObjectContext.performAndWait({
do{
let tvInfoResult = try self.coreDataStack.managedObjectContext.fetch(tvInfoRequest)
tvShows = tvInfoResult
} catch {
fatalError("Error fetching channels displayShow")
}
})
I thought maybe some issue with progId (type mismatch Int64), so I tried fetching using the tvShow name (with exact showNames from tvInfo table still getting only one result, (first name passed in the array)
tvInfoRequest.predicate = NSPredicate(format: "progName MATCHES %#", argumentArray: ["Supercar Superbuild","Kanahiya Bhaiya Live"])
weird thing is I used the same logic to fetch progIds from channels Table and its working fine(getting progId with exact matches) and its working for other tables also like channel Id fetching from channel tables
// fetching progIds from channel table
let tvScheduleRequest: NSFetchRequest<TvSchedule> = TvSchedule.fetchRequest()
tvScheduleRequest.predicate = NSPredicate(format: "chId == %i", argumentArray: channelIds)
tvScheduleRequest.returnsDistinctResults = true
var progId = [Int64]()
coreDataStack.managedObjectContext.performAndWait({
do{
let tvScheduleResult = try self.coreDataStack.managedObjectContext.fetch(tvScheduleRequest)
if tvScheduleResult.count > 0 {
for array in tvScheduleResult {
progId.append(array.progId)
}
}
} catch {
fatalError("Error fetching channels to display show")
}
})
PS:
Its returning 1 row so it's not an issue of context, wrong key,
thread
there are data in table as if I don't apply any predicate its
returning 100+ rows
I am using argumentArray for predicate, not single args CVarArg.
Thanks for help
In predicate try using %# instead of %i.
tvInfoRequest.predicate = NSPredicate(format: "progId == %i", argumentArray: progId).
One more thing check the variable that you are passing to predicate progId.
I am trying to retrieve CLOB data via ODP.NET.
My problem is that reader.GetValue(i).ToString() can return only up to 4000 characters and the rest of the data is truncated.
If I use reader.GetOracleClob(1).Value I got "Specified cast is not valid" error.
Any idea what I have missed? I am using ODP.NET 4.0
Below is my code.
using (OracleConnection oConn = new OracleConnection())
{
oConn.ConnectionString = pConnstr;
oConn.Open();
using (OracleCommand oCmd = new OracleCommand("select varchar_column, clob_column from test", oConn))
{
oCmd.InitialLOBFetchSize = -1;
string key, value, value1;
var rd = oCmd.ExecuteReader();
while (rd.Read())
{
if (rd.IsDBNull(1)) { value = ""; }
else
{
key = rd.GetValue(0).ToString();
value = rd.GetValue(1).ToString(); // unable to get more than 4000.
value1 = rd.GetOracleClob(1).Value; // Specified cast is not valid.
}
}
}
}
I found in Oracle Doc that When the InitialLOBFetchSize property is set to a nonzero value, the GetOracleBlob, GetOracleClob, GetOracleBlobForUpdate, and GetOracleClobForUpdate typed accessor methods are disabled. That may help explain why I got "Specified cast is not valid" error.
However, I still cannot get data beyond 4000 limit.
I have tried different combinations documented here
http://docs.oracle.com/cd/E11882_01/win.112/e18754/featData.htm#autoId6
But no luck.
Actually the code works correctly and gets the data it supposed to get. I just didn't realize that my data is incomplete and appeared to be a retrieval problem at the first look. Sorry.
The following is the good code.
using (OracleConnection oConn = new OracleConnection())
{
oConn.ConnectionString = pConnstr;
oConn.Open();
using (OracleCommand oCmd = new OracleCommand("select varchar_column, clob_column from test", oConn))
{
oCmd.InitialLOBFetchSize = -1;
string key, value;
var rd = oCmd.ExecuteReader();
while (rd.Read())
{
if (rd.IsDBNull(1)) { value = ""; }
else
{
key = rd.GetValue(0).ToString();
value = rd.GetValue(1).ToString();
}
}
}
}
The above solution did not work for me. It turns out my data was not CLOB or BLOB but LONG Data! So the fix is just to set:
oCmd.InitialLONGFetchSize= -1;
Instead of
oCmd.InitialLOBFetchSize = -1;
Please leave a comment if this method worked for you also.
Following AlexEdge Tutorial I have encountered the following behavior. I can provide code as requested since there are many lines and I'm not really sure where to look. Basically, it "works" in the sense that the data is properly loaded into the UITableView, but after stopping and starting up the simulator, it inserts new duplicate rows in each section.
I figured this would have something to do with caching but I am following the above tutorial pretty closely and I've set the identificationAttributes to identify unique records (wouldn't, for example, adding ALL attributes effectively eliminate the possibility that I've not specified a sufficiently unique key, just for debugging purposes?). I've tried changing the Cache name, setting it nil, but it keeps inserting duplicates. Every so often I reset the simulator just to start on a clean slate.
If it matters, I am calling getObjectsAtPath in viewDidLoad as per the tutorial. My understanding of how RestKit worked was that it was okay to do so because it would be smart enough to infer that no updates were necessary as the records are all the same.
Edit
I have set identificationAttributes to an array of two integer attributes that really do determine a unique record.
I also have a managedObjectCache:
// Seal the deal
[managedStore createPersistentStoreCoordinator];
NSString *storePath = [RKApplicationDataDirectory() stringByAppendingPathComponent:#"CCTDB.sqlite"];
NSError *error;
NSPersistentStore *persistentStore =
[managedStore
addSQLitePersistentStoreAtPath:storePath
fromSeedDatabaseAtPath:nil
withConfiguration:nil
options:#{
NSMigratePersistentStoresAutomaticallyOption:#YES,
NSInferMappingModelAutomaticallyOption:#YES
}
error:&error];
NSAssert(persistentStore, #"Failed to add persistent store with error: %#", error);
[managedStore createManagedObjectContexts];
managedStore.managedObjectCache = [[RKInMemoryManagedObjectCache alloc] initWithManagedObjectContext:managedStore.persistentStoreManagedObjectContext];
EDIT 1
Here is the log output of the second time around
(2013-07-11 03:18:29.961 cocoaclinical[18773:3d07] D restkit.object_mapping:RKPropertyInspector.m:130 Cached property inspection for Class 'EMDisease': {
diseaseId = {
isPrimitive = 0;
keyValueCodingClass = NSNumber;
name = diseaseId;
};
diseaseIdValue = {
isPrimitive = 1;
keyValueCodingClass = NSNumber;
name = diseaseIdValue;
};
name = {
isPrimitive = 0;
keyValueCodingClass = NSString;
name = name;
};
subDiseaseId = {
isPrimitive = 0;
keyValueCodingClass = NSNumber;
name = subDiseaseId;
};
subDiseaseIdValue = {
isPrimitive = 1;
keyValueCodingClass = NSNumber;
name = subDiseaseIdValue;
};
}
2013-07-11 03:18:29.975 cocoaclinical[18773:3f03] I restkit.core_data:RKInMemoryManagedObjectCache.m:94 Caching instances of Entity 'EMDisease' by attributes 'diseaseId, subDiseaseId'
2013-07-11 03:18:29.983 cocoaclinical[18773:3f03] T restkit.core_data:RKInMemoryManagedObjectCache.m:127 Cached 31 objects
2013-07-11 03:18:29.984 cocoaclinical[18773:3f03] D restkit.object_mapping:RKMapperOperation.m:231 Asked to map source object {
DiseaseSystemIdMember = 161;
DisplayNameMember = "Acute Lymphocytic Leukemia";
SubDiseaseSystemIdMember = 1886;
} with mapping <RKEntityMapping:0x96c2850 objectClass=EMDisease propertyMappings=(
"<RKAttributeMapping: 0x96ba060 SubDiseaseSystemIdMember => subDiseaseId>",
"<RKAttributeMapping: 0xb58df40 DisplayNameMember => name>",
"<RKAttributeMapping: 0xb58df70 DiseaseSystemIdMember => diseaseId>"
)>
2013-07-11 03:18:29.984 cocoaclinical[18773:3f03] D restkit.object_mapping:RKMappingOperation.m:952 Starting mapping operation...
2013-07-11 03:18:29.985 cocoaclinical[18773:3f03] T restkit.object_mapping:RKMappingOperation.m:953 Performing mapping operation: <RKMappingOperation 0xb5b7820> for 'EMDisease' object. Mapping values from object {
DiseaseSystemIdMember = 161;
DisplayNameMember = "Acute Lymphocytic Leukemia";
SubDiseaseSystemIdMember = 1886;
} to object <EMDisease: 0xb5b7ee0> (entity: EMDisease; id: 0xb5b7f80 <x-coredata:///EMDisease/t8DD8EE18-C798-468F-9E03-C6A3C724AA772> ; data: {
diseaseId = 161;
name = nil;
subDiseaseId = 1886;
}) with object mapping (null)
2013-07-11 03:18:30.027 cocoaclinical[18773:3f03] T restkit.object_mapping:RKMappingOperation.m:550 Mapping attribute value keyPath 'SubDiseaseSystemIdMember' to 'subDiseaseId'
2013-07-11 03:18:30.028 cocoaclinical[18773:3f03] T restkit.object_mapping:RKMappingOperation.m:583 Skipped mapping of attribute value from keyPath 'SubDiseaseSystemIdMember to keyPath 'subDiseaseId' -- value is unchanged (1886)
2013-07-11 03:18:30.029 cocoaclinical[18773:3f03] T restkit.object_mapping:RKMappingOperation.m:550 Mapping attribute value keyPath 'DisplayNameMember' to 'name'
2013-07-11 03:18:30.029 cocoaclinical[18773:3f03] T restkit.object_mapping:RKMappingOperation.m:572 Mapped attribute value from keyPath 'DisplayNameMember' to 'name'. Value: Acute Lymphocytic Leukemia
2013-07-11 03:18:30.030 cocoaclinical[18773:3f03] T restkit.object_mapping:RKMappingOperation.m:550 Mapping attribute value keyPath 'DiseaseSystemIdMember' to 'diseaseId'
2013-07-11 03:18:30.030 cocoaclinical[18773:3f03] T restkit.object_mapping:RKMappingOperation.m:583 Skipped mapping of attribute value from keyPath 'DiseaseSystemIdMember to keyPath 'diseaseId' -- value is unchanged (161)
2013-07-11 03:18:30.031 cocoaclinical[18773:3f03] D restkit.object_mapping:RKMappingOperation.m:1021 Finished mapping operation successfully...
You do need to set identificationAttributes, generally only one or two attributes though, not everything. Your entities should have some unique identifier.
You also want to add a managedObjectCache to your managed object store. This is the part that allows RestKit to match objects using your identificationAttributes and update the existing items instead of creating new ones.
I have a plugin that is registered Update, Order, Post Operation. In the plugin I perform a retrievemultiple on the salesorderdetail. The problem I'm having is that there are 3 products that make up the order but I am returning 5 rows from the retrieve operation. I have added and deleted the same product multiple times during my testing and I'm not sure if that's what's causing the problem. I was thinking that after deleting a product from the order it may set a flag and get deleted after, but I don't see a status code or state code as an attribute. Why would it return too many rows?
Here is my code...
// Set the properties of the QueryExpression object.
orderDetailQuery.EntityName = "salesorderdetail";
orderDetailQuery.ColumnSet = orderDetailColumnSet;
EntityCollection salesOrderDetail = service.RetrieveMultiple(orderDetailQuery);
orderProductQuery.EntityName = "product";
orderProductQuery.ColumnSet = orderProductColumnSet;
foreach (var orderDetail in salesOrderDetail.Entities)
{
if(orderDetail.Attributes.Contains("productid"))
{
productGuid = ((EntityReference)orderDetail["productid"]).Id;
Entity product = service.Retrieve("product", productGuid, orderProductColumnSet);
}
}
Thank you for the help!!
The code you posted does not show you filtering for the specific Order.
I would expect that to retrieve all entities of that type in the system.
To filter, assuming you are using a QueryByAttribute, is to add an filter along the lines of:
var query = new QueryByAttribute();
query.EntityName = "salesorderdetail";
query.AddAttributeValue("orderid", orderId);//orderId is the Id of the parent Order
orderDetailQuery.EntityName = "salesorderdetail";
orderDetailQuery.ColumnSet = orderDetailColumnSet;
var results = service.RetrieveMultiple(query);
That way you are restricting your query to just products for the given order.
I'm not sure that your filtering is implemented. Here's a shot from the hip on how you could query for instances of SalesOrderDetail entity, fetching the values of fieldName1 and fieldName2 fields provided that the it's linked to the order with guid orderId.
QueryExpression query = new QueryExpression
{
EntityName = "salesorderdetail",
ColumnSet = new ColumnSet("fieldName1", "fieldName2"),
Criteria = new FilterExpression
{
Conditions =
{
new ConditionExpression
{
AttributeName = "orderid",
Operator = ConditionOperator.Equal,
Values = { orderId }
}
}
}
};
I have array output like this.
{
id = 1;
user = {
name="ABC"
}
},
{
id = 2;
user = {
name="XYZ"
}
},
I have to change id with number 5 and 6 and name with "asd" and "fgh". My array definition is here.
myArray=[[NSMutableArray alloc]initWithArray:statuses];
And here is my approach for chaning of "id".
[[myArray objectAtIndex:0]replaceObjectAtIndex:0 withObject:#"5"];
[[myArray objectAtIndex:0]replaceObjectAtIndex:0 withObject:#"6"];
But I am getting following acception.
[__NSCFDictionary replaceObjectAtIndex:withObject:]: unrecognized selector sent to instance 0x6511810
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary replaceObjectAtIndex:withObject:]: unrecognized selector sent to instance 0x6511810'
myArray seems to be NSArray which is Immutable.
How did you declare myArray?
EDIT:
First:
myArray = [statuses mutableCopy];
Second:
[[myArray objectAtIndex:0] setObject:#"5" forKey:#"id"];
[[myArray objectAtIndex:1] setObject:#"6" forKey:#"id"];
[[[myArray objectAtIndex:0] objectForKey:#"user"] setObject:#"asd" forKey:#"name"];
[[[myArray objectAtIndex:1] objectForKey:#"user"] setObject:#"fgh" forKey:#"name"];