I am applying some criteria query to find the sum of columns and save the result in long format. When there is data in the table, it is working fine, but in case no match records are found, the following error is thrown:
Cannot cast object 'null' with class 'null' to class 'long'**
My code is:
long referralPoints = ReferralDetail.createCriteria().get {
eq('referredBy', user)
projections {
sum('referralPoints')
}
}
Use Long instead of long. Primitives cannot be null.
Related
I am a bit confused on how to deal with complex Swift data types, their assignment to variables and accessing the values within. Hopefully someone can clarify the following:
when trying to get data from SwiftUI and CloudKit, and while trying to rewrite a CK function to conform to async/await, I have the following line of code:
let result = try await container.privateCloudDatabase.records(matching: query)
now this line is supposed to get all of the records matching the specified query from the cloud private database and return some CKRecords
The old function did this as follows:
container.privateCloudDatabase.perform(query, inZoneWith: nil) { (rec, err) in
for record in rec {
print("Found this record: \(record)")
}
}
and this worked great because perform(_:inZoneWith:) would return a CKRecord and an Error, those were "picked apart" in the (rec, err) in statement and passed into the loop to be iterated.
With the new async/await method, I am trying to simply await and assign a variable to all of the records that are found and then iterate the data returned, pick out the CKRecords and perform whatever task I want.
What I am confused with is, when I attempt to pick out the data from the returned result, in several ways, I just get errors. I am not fully understanding how to describe the data structure of the returned values and I think this is the root cause of the issue.
I have tried a few things and have gotten the following error messages:
if I try:
let (result, err) = try await container.privateCloudDatabase.records(matching: query)
When I use (trying to append the CKRecords to an array of CKRecords I created earlier):
for record in result {
self.myCKRecordArray.append(record)
}
the error message states specifically:
Cannot convert value of type 'Dictionary<CKRecord.ID, Result<CKRecord, Error>>.Element' (aka '(key: CKRecord.ID, value: Result<CKRecord, Error>)') to expected argument type 'CKRecord'
Which definitely gives me some clues. I believe that my result variable contains a Dictionary<CKRecord.ID, Result<CKRecord, Error>>.Element, or a list of key/value pairs wherein the CKRecord.ID is the key for the Result<CKRecord, Error> value.
This is pretty confusing.. So If I understand that correctly, then:
for thisDict in result {
let (realResult, err) = result[thisDict.key]
print("Found this record: \(realResult)")
}
should theoretically result in the output of each CKRecord assigned to realResult, right? I just get the error: Type of expression is ambiguous without more context
I tried to change it to valueForKey and also give it more context, but no change from the error message:
let (realResult, err) = result(valueForKey:thisDict.key) as Result<CKRecord, Error>
I just believe that I do not fully understand how to properly access the CKRecord from something that is represented by a: Dictionary<CKRecord.ID, Result<CKRecord, Error>>.Element data structure.
Any insight into understanding is greatly appreciated.
Thank you
Update
Ok, based on the answer from #Shadowrun, if I understand correctly:
The result from:
let result = try await container.privateCloudDatabase.records(matching: query)
is a tuple type. Which means that it has two elements, the first being the Dictionary of data and the second being the queryCursor.
If I want to iterate over the Dictionary portion of the tuple and get the CKRecord out:
for rec in result.0 {
self.myCKRecordArray.append(try rec.value.get())
}
This does not give me any errors.. Am I understanding this correctly?
2nd update
it does work as expected this way.
There’s an equivalence between functions that return a Result<T, E> and functions that either return T or throw an E. And similar equivalence for functions returning tuple of (T?, E?)
When mapping functions with completion handlers to async functions, they become throwing functions, so should just be:
let result = try await container….
The error, if any, is thrown
At the risk of being pedantic, may I suggest reading the docs?
https://developer.apple.com/documentation/cloudkit/ckdatabase/3794332-records
func records(matching query: CKQuery,
inZoneWith zoneID: CKRecordZone.ID? = nil,
desiredKeys: [CKRecord.FieldKey]? = nil,
resultsLimit: Int = CKQueryOperation.maximumResults) async throws ->
(matchResults: [CKRecord.ID : Result<CKRecord, Error>],
queryCursor: CKQueryOperation.Cursor?)
So your result is tuple. Call your result tuple. Then tuple.matchResults is a dictionary keyed by ID whose values are Result objects.
The best way to extract value from a Result object, in my opinion, is to use get. This has the advantage that it either returns a value or throws, and you can cope nicely with that.
So am using AspNetCore 1.0 with EFCore 1.0, both latest releases as far as I am aware.
Executing a query to delete an object using the FromSql method on a DbSet throws an exception. Both the code and exception are below.
public void DeleteColumn(int p_ColumnID)
{
int temp = p_ColumnID;
string query = "DELETE FROM Columns WHERE ID = {0}";
var columnsList = m_context.Columns.FromSql(query, p_ColumnID).ToList();
foreach (Columns c in columnsList)
{
m_context.Columns.Remove(c);
}
m_context.SaveChanges();
}
After executing the FromSql call, I get the following exception
An exception of type 'System.NotSupportedException' occurred in Remotion.Linq.dll but was not handled in user code
Additional information: Could not parse expression 'value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1[ASPNET5_Scrum_Tool.Models.Columns]).FromSql("DELETE FROM Columns WHERE ID = {0}", __p_0)': This overload of the method 'Microsoft.EntityFrameworkCore.RelationalQueryableExtensions.FromSql' is currently not supported.
I have no clue how to fix this error and from Googling I have come across no similar problems.
I am also wondering, if the query/code was successful it would return an 'IQueryable object. Would that solely contain the results of the query, in this case the specific Column object to delete?
FromSql is intended to allow you to compose a custom SQL SELECT statement that will return entities. Using it with a DELETE statement is not appropriate here, since your goal is to load the records you want to delete and then delete them using the default Entity Framework mechanism. A Delete statement generally does not return the records deleted (though there are ways to accomplish that). Even if they did, the records will already be deleted and so you won't want to iterate over them and do a Remove on them.
The most straightforward way to do what you want might be to use the RemoveRange method in combination with a Where query.
public void DeleteColumn(int p_ColumnID)
{
m_context.Columns.RemoveRange(m_context.Columns.Where(x => x.ID == p_ColumnID))
m_context.SaveChanges();
}
Alternately, if you want to load your entities and iterate manually through them to
public void DeleteColumn(int p_ColumnID)
{
columnList = m_context.Columns.Where(x => x.ID == p_ColumnID);
foreach (Columns c in columnsList)
{
m_context.Columns.Remove(c);
}
m_context.SaveChanges();
}
If you really want to issue the Delete statement manually, as suggested by Mike Brind, use an ExecuteSqlCommand method similar to:
public void DeleteColumn(int p_ColumnID)
{
string sqlStatement = "DELETE FROM Columns WHERE ID = {0}";
m_context.Database.ExecuteSqlCommand(sqlStatement, p_ColumnID);
}
I had the same exception in a case where I did not use delete statement. Turns out I was using the In-Memory Database. Since it is not a real database you can't use FromSQL.
I have the following (simplified) Entity SQL query:
SELECT VALUE a
FROM Customers AS a
WHERE a.Status NOT IN { 2, 3 }
The Status property is an enumeration type, call it CustomerStatus. The enumeration is defined in the EDMX file.
As it is, this query doesn't work, throwing an exception to the effect that CustomerStatus is incompatible with Int32 (its underlying type is int). However, I couldn't find a way to define a list of CustomerStatus values for the IN {} clause, no matter what namespace I prefixed to the enumeration name. For example,
SELECT VALUE a
FROM Customers AS a
WHERE a.Status NOT IN { MyModelEntities.CustomerStatus.Reject, MyModelEntities.CustomerStatus.Accept }
did not work, throwing an exception saying it could not find MyModelEntities.CustomerStatus in the container, or some such.
Eventually I resorted to casting the Status to int, such as
SELECT VALUE a
FROM Customers AS a
WHERE CAST(a.Status AS System.Int32) NOT IN { 2, 3 }
but I was hoping for a more elegant solution.
Oooh, you are writing Entity SQL directly. I see... Any reason you aren't using DbSet instead of writing Entity SQL by hand? Could always do
var statuses = new [] { Status.A, Status.B };
var query = context.SomeTable.Where(a => !statuses.Contains(a.Status)).ToList();
I am getting this error: Cannot get property 'id' on null object and i can't understand the problem.
Here is my code in provionController.groovy
CreateCriteria returns one element, I verified in the database, size = 1 but when i tried to display the Id, I get this error.
def prov_model = null
def model = Provision_model.CreateCriteria{
gilt_air{
eq("air",air)
}
gilt_coo{
eq("coo",coo)
}
le("date_from", per.begin)
ge("date_to", per.end)
eq("active", 1)
}
println(model.size())
prov_model = model[0]
println(prov_model.id)
but when I am getting it directly by method get(), it hasn't no problem
prov_model = Provision_model.get(57)
println(prov_model.id)
1st: the method is called createCriteria(), not CreateCriteria()
2nd: the method itself DOES NOT invoke any db operation. You have to call list() or get() etc. on it to get the query results
If order to execute the query and store the results in model, replace this
def model = Provision_model.CreateCriteria
with
def model = Provision_model.withCriteria
#injecteer and #Donal both have very valid input. First, you need to address the syntax issue, here is an example of one way to format your criteria:
def prov_model = null
def model = Provision_model.createCriteria().get() {
gilt_air{
eq("air",air)
}
gilt_coo{
eq("coo",coo)
}
le("date_from", per.begin)
ge("date_to", per.end)
eq("active", 1)
}
Keep in mind that by using .get() you are limiting the return from the criteria to one record. Second, if you try writing the criteria both ways, using withCriteria and using the format above and it still doesn't work, your problem may be in the domain model or the configuration of the database.
I am trying to create a Predicate using a decimal data type but I get the following error:
Error retrieving data.A binary operator with incompatible types was detected.
Found operand types 'Edm.Decimal' and 'Edm.Double' for operator kind 'Equal'.
Error: A binary operator with incompatible types was detected. Found operand types
'Edm.Decimal' and 'Edm.Double' for operator kind 'Equal'.
Here is the code I am trying it with:
// engineSize equals 1.4 in this case.
predicate.create('engineLitreCapacity', '==', engineSize);
I'had the same issue. I found the mistery :)... I think that's somethings in naming convention related to metadata and the REST service controller sign: Eg:
Doesn't work
/*Breeze Controller Server Side*/
[HttpGet]
public IQueryable<Product> Items()
{
return _contextProvider.Context.Products;
}
/*Client*/
query = breeze.EntityQuery
.from("Items")
.where(Predicate.create('BasePrice', >', 1)
.orderBy(sortString)
.select(selectData)
.skip(skip)
.take(take)
.inlineCount();
It' works !!
/*Breeze Controller Server Side*/
[HttpGet]
public IQueryable<Product> Products()
{
return _contextProvider.Context.Products;
}
/*Client*/
query = breeze.EntityQuery
.from("Products")
.where(Predicate.create('BasePrice', >', 1)
.orderBy(sortString)
.select(selectData)
.skip(skip)
.take(take)
.inlineCount();
You need to parseFloat the engineSize:
predicate.create('engineLitreCapacity', '==', parseFloat(engineSize));
What is the datatype in metadata for the 'engineLitreCapacity' and does it match the datatype on your database for the same field? If not, how was your metadata initialized, via a FetchMetadata call or was it created by hand?