Core Data migration issue - selector error - core-data

I've added a new attribute to one of my entities, core data has migrated it and is loading the app fine, not showing the incompatible model error, but when it comes to using the new attribute i'm getting selector errors, i would assume since theres nothing there yet, how do i get it so that if theres no data it just shows an empty string.
I've tried
var string : String = "No value"
if let d : NSDate = lastTaken
{
let hours : NSNumber = hoursBetween!
let hoursAsSeconds : NSTimeInterval = hours.doubleValue * 3600
let time : NSDate = d.dateByAddingTimeInterval(hoursAsSeconds)
let formatter : NSDateFormatter = NSDateFormatter()
formatter.dateFormat = "MMM dd, HH:mm"
formatter.timeZone = NSTimeZone.defaultTimeZone()
string = formatter.stringFromDate(time)
}
return string
but it still throws the selector error. lastTaken is the new attribute
Full error
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[M lastTaken]: unrecognized
selector sent to instance 0x12dd11b30'
if i edit out the if section, then the app runs and shows the no value string

It looks like you updated the Core Data model but didn't update your custom subclass of NSManagedObject. Now you're trying to access lastTaken, but the class doesn't have a property with that name. Re-generate the subclass, or add the new property to the class by hand.

Related

Swift CoreData subclass not working

i know that this has been asked a couple of times but the usual solution does not seem to work for me. I created a CoreData entity and a subclass for it using <ProjectName>.<SubclassName> syntax as class name. Creating a new object like this:
let object = NSEntityDescription.insertNewObjectForEntityForName("User", inManagedObjectContext: CoreDataManager.sharedInstance.managedObjectContext) as User
println("-->\(object)<--")
object.setValue(12, forKey: "userID")
object.setValue("username", forKey: "username")
the console output:
although the object does not get printed in the console it seems to have been in some way created and setting a value on that object refers to a Core Data Object
when i use it without a subclass it works as expected (setting Class name back to default):
let object = NSEntityDescription.insertNewObjectForEntityForName("User", inManagedObjectContext: CoreDataManager.sharedInstance.managedObjectContext) as NSManagedObject
println("-->\(object)<--")
output:
Here's my subclass declaration:
import Foundation
import CoreData
class User: NSManagedObject {
#NSManaged var userID: NSNumber
#NSManaged var username: String
}
and here's the core data model form:
What's wrong with the code? Or do i miss anything?
For printing out the value of an NSManagedObject, do not use:
println(...)
But rather use:
NSLog(...)
Please find an example of using NSLog and an NSManagedObject below:
/**
* Called when the user clicks on the save button.
*/
#IBAction func saveTapped(sender: AnyObject) {
// Reference to our app delegate
let appDel: AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
// Reference MOC
let context: NSManagedObjectContext = appDel.managedObjectContext!
let en = NSEntityDescription.entityForName("List", inManagedObjectContext: context)
// Create instance of put data model and initialize
var newItem: List = List(entity: en!, insertIntoManagedObjectContext: context)
// Map our properties
newItem.item = textFieldItemName.text
newItem.quantity = textFieldQt.text
newItem.info = textFieldMoreInfo.text
// Save our context
var error: NSError? = nil;
if (context.hasChanges) {
if (!context.save(&error)) { // save failed
println("Save Failed: \(error!.localizedDescription)")
} else {
println("Save Succeeded")
}
}
NSLog("newItem: %#", newItem)
// Navigate back to root ViewController
self.navigationController?.popToRootViewControllerAnimated(true)
}
Note: I do not know the exact reason (bug, or implementation maybe ...) but it turns out that it does not print out a value when we use println(...) function, instead of that it returns an empty String.
Consequently I recommend to all of you guys to use NSLog(...) function instead of println(...) when you want to print out the value of an NSManagedObject.
If you print the expression CoreDataManager.sharedInstance.managedObjectContext twice, do you get a different pointer each time?
It sounds like the managed object context is getting deallocated right after you use it, which indicates that your CoreDataManager.sharedInstance.managedObjectContext property is returning a new managed object context every time, not the same one, or your sharedInstance property is returning a new instance every time.
A managed object's in-memory state is stored as a weak reference to a managed object context. When the context drops out from underneath you (e.g. it's no longer referenced and so is deallocated), your managed object's storage disappears.
A few good indicators that this is happening:
You haven't saved your managed object context yet but a newly created managed object prints as fault
You get weird errors when you try to set a property
You get weird errors when you try to retrieve a property you just set
Include the following at the top of your .swift file
import CoreData
The reason for not working is it doesn't know which library to reference.
Hope it helps
try creating it with this method :
let entityDescripition = NSEntityDescription.entityForName(“User”, inManagedObjectContext: managedObjectContext)
let user = User(entity: entityDescripition, insertIntoManagedObjectContext: managedObjectContext)

Error during run OrganizationRequest 'RetrieveAllEntities'

I got this error during execute, could anyone give suggestion? Thanks
OrganizationRequest oreq = new OrganizationRequest();
oreq.RequestName = "RetrieveAllEntities";// please google for available Request Names
oreq.Parameters = new ParameterCollection();
oreq.Parameters.Add(new KeyValuePair<string, object>("EntityFilters", EntityFilters.Entity));
oreq.Parameters.Add(new KeyValuePair<string, object>("RetrieveAsIfPublished", false));
OrganizationResponse respo = orgProxy.Execute(oreq);
"The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter schemas.microsoft.com/xrm/2011/Contracts/Services:ExecuteResult. The InnerException message was 'Error in line 1 position 727. Element 'schemas.datacontract.org/2004/07/System.Collections.Generic:value' contains data of the 'schemas.microsoft.com/xrm/2011/Metadata:ArrayOfEntityMetadata' data contract. The deserializer has no knowledge of any type that maps to this contract. Add the type corresponding to 'ArrayOfEntityMetadata' to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding it to the list of known types passed to DataContractSerializer.'. Please see InnerException for more details."
Add a reference to Microsoft.Crm.Sdk.Proxy and Microsoft.Xrm.Sdk. Visual Studio may tell you that you need to add an additional couple System.* references - add them.
Use this code:
IOrganizationService service = GetCrmService(connectionString); //This is a helper, just need to setup the service
var request = new Microsoft.Xrm.Sdk.Messages.RetrieveAllEntitiesRequest()
{
EntityFilters = Microsoft.Xrm.Sdk.Metadata.EntityFilters.All,
RetrieveAsIfPublished = false
};
var response = (Microsoft.Xrm.Sdk.Messages.RetrieveAllEntitiesResponse)service.Execute(request);
Get it work finally there is two KnownTypeAttribute need to be added to the proxy class
**[System.Runtime.Serialization.KnownTypeAttribute(typeof(EntityMetadata[]))]**
public partial class OrganizationRequest : object, System.Runtime.Serialization.IExtensibleDataObject
....
**[System.Runtime.Serialization.KnownTypeAttribute(typeof(EntityMetadata[]))]**
public partial class OrganizationResponse : object, System.Runtime.Serialization.IExtensibleDataObject
Thank you for help.

Get entity record values from Audit Details Response

Auditing of an entity is enabled,I want the entity record after deletion.So
I was trying to get that from audit entity records,like this:
RetrieveAuditDetailsRequest request = new RetrieveAuditDetailsRequest();
request.AuditId = _selectedId;
RetrieveAuditDetailsResponse response = (RetrieveAuditDetailsponse)_orgService.Execute(request);
EntityReference ObjectId = (EntityReference)response.AuditDetail.AuditRecord.Attributes["objectid"];
string ObjectName = ObjectId.LogicalName;
Guid Id = ObjectId.Id;
ColumnSet col = new ColumnSet(true);
Entity ent = _orgService.Retrieve(ObjectName,Id,col);
Its throwing an error "Expected non empty Guid".
FYI, I want this record values because I want to restore/recover record by creating it again.
Please help whats wrong with it??
You are attempting to retrieve the deleted record with this code:
string ObjectName = ObjectId.LogicalName;
Guid Id = ObjectId.Id;
ColumnSet col = new ColumnSet(true);
Entity ent = _orgService.Retrieve(ObjectName,Id,col);
This will fail with the error you are getting because no such record exists (it is deleted.) Unlike CRM 4 and earlier there are no soft deletes in 2011, once deleted it is gone from the database.
Replace it with the following code:
RetrieveRecordChangeHistoryRequest retrieveRequest = new RetrieveRecordChangeHistoryRequest();
changeRequest.Target = new EntityReference(ObjectName, Id);
RetrieveRecordChangeHistoryResponse response =
(RetrieveRecordChangeHistoryResponse)_orgService.Execute(retrieveRequest);
if (response.AuditDetailCollection != null)
{
var auditDetails = response.AuditDetailCollection;
// Do work
}
You then enumerate through the auditDetails to get the correct attributes.
You can find more at http://blogs.msdn.com/b/crm/archive/2011/05/23/recover-your-deleted-crm-data-and-recreate-them-using-crm-api.aspx.
The "Expected non empty Guid" error is thrown whenever you try to retrieve something with an empty GUID (Guid.Empty, 00000000-0000-0000-0000-000000000000). I'm guessing your _selectedId is not set to an actual GUID. Maybe you're setting it from a Nullable GUID and you are calling ValueOrDefault(), which is resulting in it getting set to the empty Guid, and failing in your Request?

How to get real T-SQL generated by Entity Framework with ToTraceString() not working

//get full list of active employees
public static object EmployeeList()
{
string traceFile = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
var empList = (from emp in dbViews.EmployeeList
where emp.StatusID == 7
orderby emp.EmpNo
select new
{
emp.id,
emp.Name,
emp.EmpNo,
emp.Telephone,
emp.EmployeeType,
emp.DepartmentName,
emp.Supervisor,
emp.ImmediateSupervisor,
emp.StatusID
});
File.AppendAllText(traceFile, ((ObjectQuery)empList).ToTraceString());
return empList.ToList();
}
When executing the above code, am getting the error below and am not sure why
*
Unable to cast object of type
'System.Data.Entity.Infrastructure.DbQuery1[<>f__AnonymousType09[System.Int32,System.String,System.String,System.String,System.String,System.String,System.String,System.String,System.Nullable`1[System.Int32]]]'
to type 'System.Data.Objects.ObjectQuery'.
*
I just want to get the real T-SQL generated by the above Entity Framework code.
The error is at line below
File.AppendAllText(traceFile, ((ObjectQuery)empList).ToTraceString());
You are using DbContext API so you can use just empList.ToString().

How do you get a new Core Data Entity attribute to be reflected in the NSManagedObject for that Entity?

I'm trying to implement a getter on one of my db classes. But when I execute the following line of code, where "obj" is an NSManagedObject:
return [obj valueForKey:#"activationData"];
I get the following NSUnknownKeyException:
'[ valueForUndefinedKey:]: the entity Blueprint is not key value coding-compliant for the key "activationData".'
I just recently added a String attribute named "activationData" to my "Blueprint" entity using Xcode. But when I run the app the NSManagedObject that represents Blueprint entities does not include the new "activationData" attribute, which apparently is the cause of the crash.
The NSManagedObject looks like this, but I expected it to show the new Attribute along with the createDate, name and order attributes:
<NSManagedObject: 0x5138c90> (entity: Blueprint; id: 0x513a2e0 <x-coredata://8C586BB8-B9E7-4FD7-84CB-5CE66FB221E6/Blueprint/p2> ; data: {
createDate = "2012-02-21 15:49:00 +0000";
name = "Feb 17 test";
order = 2;
})
Fyi, user1226119's answer (below) reminded me that I used the Organizer to extract the sqlite db from my device and inspect it with SQLite Manager to verify things. Sure enough there is still no new activationData field in the Blueprint table. The table looks the same as it always did.
I think I must have missed some necessary step for adding a new Attribute to an existing db Entity.
Your model has not change in your app. You must delete your old application and re-deploy your app on your device.
The solution was to update the pathForResource method call in the code that returns the NSManagedObjectModel. I had indeed created a new xcdatamodel version of the db before adding the attribute, but apparently you are supposed to refer to it using the following code, which retrieves the model your app will use.
- (NSManagedObjectModel *)managedObjectModel {
if (managedObjectModel != nil) {
return managedObjectModel;
}
NSString *path = [[NSBundle mainBundle] pathForResource:#"MyDB Version5" ofType:#"mom" inDirectory:#"ASSIST.momd"];
NSURL *momURL = [NSURL fileURLWithPath:path];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURL];
return managedObjectModel;
}
I had to put the new database version's name ("MyDB Version5") as the pathForResource parameter. Previously it was "MyDB Version5".

Resources