Selecting values from IQueryable with IsNullOrWhitespace check - linq

I am trying to do the following with a IQueryable expression:
(from Person p in s
select new
{
label = p.FirstName + " "
+ (string.IsNullOrWhiteSpace(p.MiddleName) ? p.MiddleName + " " : "")
+ p.LastName,
value = p.Id
}).ToList();
I am getting following error:
LINQ to Entities does not recognize the method 'Boolean
IsNullOrWhiteSpace(System.String)' method, and this method cannot be
translated into a store expression.
What is the solution for this?

String.IsNullOrWhitespace is a static function of the string object and cannot be used with Entity Framework queries, whereas p.FirstName.StartsWith("S") is a method of the entity property and can be used.
To answer your question you will have to roll your own inline. Try this:
(from Person p in s
select new
{
label = p.FirstName + " "
+ ((p.MiddleName != null && p.MiddleName != string.Empty) ? p.MiddleName + " " : "")
+ p.LastName,
value = p.Id
}).ToList();

Related

Failed to get #Query Result

Hello I'm trying to read tables related with ManyToOne , i get the result when i execute the query in Navicat :
but when i try to display data in the front with angular i failed i get only the main tables
this is the query :
//like this
#Query(value = "SELECT\n" +
"\tnotification.idnotif,\n" +
"\tnotification.message,\n" +
"\tnotification.\"state\",\n" +
"\tnotification.title,\n" +
"\tnotification.\"customData\",\n" +
"\tnotification.\"date\",\n" +
"\tnotification.receiver,\n" +
"\tnotification.sender,\n" +
"\tnotification.\"type\",\n" +
"\thospital.\"name\",\n" +
"\thospital.\"siretNumber\",\n" +
"\tusers.firstname,\n" +
"\tusers.\"isActive\" \n" +
"FROM\n" +
"\tnotification\n" +
"\tINNER JOIN hospital ON notification.receiver = :reciver\n" +
"\tINNER JOIN users ON notification.sender = :sender",nativeQuery = true)
List<Notification> findNotificationCustomQuery(#Param("reciver") Long reciver,#Param("sender") Long sender);
please what can i do to resolve this problem !
You are doing inner join in the native query. Follow as below. Change the return type to Object[] from Notification.
#Query(value = "SELECT\n" +
"\tnotification.idnotif,\n" +
"\tnotification.message,\n" +
"\tnotification.\"state\",\n" +
"\tnotification.title,\n" +
"\tnotification.\"customData\",\n" +
"\tnotification.\"date\",\n" +
"\tnotification.receiver,\n" +
"\tnotification.sender,\n" +
"\tnotification.\"type\",\n" +
"\thospital.\"name\",\n" +
"\thospital.\"siretNumber\",\n" +
"\tusers.firstname,\n" +
"\tusers.\"isActive\" \n" +
"FROM\n" +
"\tnotification\n" +
"\tINNER JOIN hospital ON notification.receiver = :reciver\n" +
"\tINNER JOIN users ON notification.sender =
:sender",nativeQuery = true)
List<Object []> findNotificationCustomQuery(#Param("reciver")
Long reciver,#Param("sender") Long sender);
Then you have to loop the result as below and get the attributes.
for(Object[] obj : result){
String is = obj[0];
//Get like above
}

Why does this ADO.NET query return no results?

I have the following code that executes a SQL statement and looks for a result.
var sql = #"select BOQ_IMPORT_ID "
+ "from ITIS_PRJ.PRJ_BOQ_IMPORT_HEADER "
+ "where PROJECT_ID = :Projectid "
+ "order by CREATED_ON desc "
+ "fetch first 1 row only";
using (var conn = new OracleConnection(ApplicationSettings.ConnectionString))
using (var cmd = new OracleCommand(sql, conn))
{
conn.Open();
cmd.Parameters.Add(LocalCreateParameterRaw("ProjectId", projectId));
var reader = cmd.ExecuteReader();
if (reader.Read())
{
byte[] buffer = new byte[16];
reader.GetBytes(0, 0, buffer, 0, 16);
var boqId = new Guid(buffer);
return boqId;
}
return null;
}
Where LocalCreateParameterRaw is declared as:
public static OracleParameter LocalCreateParameterRaw(string name, object value)
{
OracleParameter oracleParameter = new OracleParameter();
oracleParameter.ParameterName = name;
oracleParameter.OracleDbType = OracleDbType.Raw;
oracleParameter.Size = 16;
oracleParameter.Value = value;
return oracleParameter;
}
The underlying type for 'projectId' is 'Guid'.
The if (reader.Read()) always evaluates to false, despite there being exactly one row in the table. It normally should return only one row.
Using GI Oracle Profiler I can catch the SQL sent to the db, but only once did the profiler provide a value for the :ProjectId parameter, and it was in lower case. Like that it returned no results, but as soon as I applied UPPER to that value, I get a result.
It looks like I somehow have to get my parameter into uppercase for the query to work, but I have no idea how. Yet if I do a ToString().ToUpper() on the projectId GUID, I get a parameter binding error.
VERY IMPORTANT:
I have tried removing the where clause altogether, and no longer add a parameter, so all rows in the table should be returned, yet still no results.
I don't know how, but making the SQL string a verbatim string (prefixed with #) causes the proc to work. So, it doesn't work with:
var sql = #"SELECT BOQ_IMPORT_ID "
+ "FROM ITIS_PRJ.PRJ_BOQ_IMPORT_HEADER "
+ "WHERE PROJECT_ID = :projectid "
+ "ORDER BY CREATED_ON DESC "
+ "FETCH FIRST ROW ONLY";
Yet the same command string in SQL Developer executes and returns results. When I make my SQL string verbatim, as below, I get results.
var sql = #"select BOQ_IMPORT_ID
from ITIS_PRJ.PRJ_BOQ_IMPORT_HEADER
where PROJECT_ID = :ProjectId
order by CREATED_ON desc
fetch first 1 row only";
Using a more general approach, try the following
var sql = "SELECT BOQ_IMPORT_ID "
+ "FROM ITIS_PRJ.PRJ_BOQ_IMPORT_HEADER "
+ "WHERE PROJECT_ID = :projectid "
+ "ORDER BY CREATED_ON DESC "
+ "FETCH FIRST ROW ONLY";
using (DbConnection conn = new OracleConnection(ApplicationSettings.ConnectionString))
using (DbCommand cmd = conn.CreateCommand()) {
DbParameter parameter = cmd.CreateParameter();
parameter.ParameterName = "projectid";
parameter.Value = projectId.ToString("N").ToUpper(); //<-- NOTE FORMAT USED
cmd.Parameters.Add(parameter);
cmd.CommandType = CommandType.Text;
cmd.CommandText = sql;
conn.Open();
var reader = cmd.ExecuteReader();
if (reader.Read()) {
var boqId = new Guid((byte[])reader[0]);
return boqId;
}
return null;
}
It looks like I somehow have to get my parameter into uppercase for the query to work, but I have no idea how. Yet if I do a ToString().ToUpper() on the projectId GUID, I get a parameter binding error.
Reference Guid.ToString Method
Specifier N formats it to 32 digits: 00000000000000000000000000000000
When no format is provided the default format is D which would include 32 digits separated by hyphens.
00000000-0000-0000-0000-000000000000
That would explain your binding error.

Only primitive types or enumeration types are supported in this context- linq join

I am getting this error when I try to join
var users = _users.Get();
var userApprovals =
(from approval in _entities.ApprovalEntities
join userDetail in users on approval.UserKey equals userDetail.UserId
where approval.EmployeeUid == employeeUid
select new UserApproval
{
Id = approval.Id,
EmployeeUid = approval.EmployeeUid,
UserKey = approval.UserKey,
UserId = approval.UserId,
UserName = userDetail.FirstName + " " + userDetail.LastName
}).ToList();
error
Only primitive types or enumeration types are supported in this context
Thanks
fixed,
var userApprovals =
(from approval in _entities.ApprovalEntities.ToList()
join userDetail in users on approval.UserKey equals userDetail.UserId
where approval.EmployeeUid == employeeUid
select new UserApproval
{
Id = approval.Id,
EmployeeUid = approval.EmployeeUid,
UserKey = approval.UserKey,
UserId = approval.UserId,
UserName = userDetail.FirstName + " " + userDetail.LastName
}).ToList();
In my case, my problem was use IEnumerable without using toList() sentence.
Look, this code show "error Only primitive types or enumeration types are supported in this context" error:
var query = db.TemplatesDocs.Where(x => x.Id_Template == idTmpl)
.Join(Utils.DocumentTypes, x => x.Id_Type, y => y.Id, (x, y) => new { tmpDoc = x, type = y } )
.ToList();
Look, this code is fixed the error:
var query = db.TemplatesDocs.Where(x => x.Id_Template == idTmpl).ToList()
.Join(Utils.DocumentTypes, x => x.Id_Type, y => y.Id, (x, y) => new { tmpDoc = x, type = y } )
.ToList();

MongoDB Native Query vs C# LINQ Performance

I am using the following two options, the Mongo C# driver seems to be taking more time. I'm using StopWatch to calculate the timings.
Case 1: Native Mongo QueryDocument (takes 0.0011 ms to return data)
string querytext = #"{schemas:{$elemMatch:{name: " + n + ",code : " + c + "} }},{schemas:{$elemMatch:{code :" + c1 + "}}}";
string printQueryname = "Query: " + querytext;
BsonDocument query1 = MongoDB.Bson.Serialization.BsonSerializer.Deserialize<BsonDocument>(querytext);
QueryDocument queryDoc1 = new QueryDocument(query1);
var queryResponse = collection.FindAs<BsonDocument>(queryDoc1);
Case 2: Mongo C# Driver (takes more than 3.2 ms to return data)
Schema _result = new Schema();
_result = (from c in _coll.AsQueryable<Schema>()
where c.schemas.Any(s => s.code.Equals(c) && s.name.Equals(n) ) &&
c.schemas.Any(s => s.code.Equals(c1))
select c).FirstOrDefault();
Any thoughts ? Anything wrong here ?

How to concat strings in LINQ while properly dealing with NULL values

I'd like an elegant way to concatenate several columns together using LINQ, but using the + operator or concat() when any of the columns are NULL results in NULL for the value after concatenation.
Is there anything similar to concat() that handles NULL differently, or am I thinking about this in the incorrect way?
Any help is appreciated!
Here is the code I am using:
List<CustomObject> objects = (
from obj in ObjectTable
where obj.Id == Id
select new CustomObject()
{
EnteredBy = obj.EnteredBy,
EntryDate = obj.EntryDate,
WorknoteText =
obj.VchWorkNote1 +
obj.VchWorkNote2 +
obj.VchWorkNote3 +
obj.VchWorkNote4 +
obj.VchWorkNote5 +
obj.VchWorkNote6 +
obj.VchWorkNote7 +
obj.VchWorkNote8 +
obj.VchWorkNote9 +
obj.VchWorkNote10 +
obj.VchWorkNote11 +
obj.VchWorkNote12 +
obj.VchWorkNote13 +
obj.VchWorkNote14 +
obj.VchWorkNote15 +
obj.VchWorkNote16 +
obj.VchWorkNote17 +
obj.VchWorkNote18 +
obj.VchWorkNote19 +
obj.VchWorkNote20
}).ToList();
One option is to use the null coalescing operator:
List<CustomObject> objects = (from o in ObjectTable
where o.Id == Id
select new CustomObject(){
EnteredBy = o.EnteredBy,
EntryDate = o.EntryDate,
WorknoteText =
(o.VchWorkNote1 ?? "") +
(o.VchWorkNote2 ?? "") +
(o.VchWorkNote3 ?? "") +
(o.VchWorkNote4 ?? "") +
...
(o.VchWorkNote20 ?? "")
}).ToList();
Hopefully the generated SQL will use an appropriate translation.
You can use the ?? operator this way :
...
(object.VchWorkNote5 ?? "") +
(object.VchWorkNote6 ?? "") +
(object.VchWorkNote7 ?? "") +
...
How about (object.VchWorkNote1 ?? "") +.....
Can you add a new column to your database? Something like "Keywords" or "FullText"
Define it to have a calculation, that calculation is basically "ISNULL(<Field1>, '') + ISNULL(<Field2>, '')" etc.
Make sure to mark it as persisted, so it doesn't have to calculate each time.
Then you just need to pull down that one field from your table.
there's probably a cleaner way, but first thing that comes to mind would be a quick null to zero length string conversion:
List<CustomObject> objects = (from object in ObjectTable
where object.Id == Id
select new CustomObject(){
EnteredBy = object.EnteredBy,
EntryDate = object.EntryDate,
WorknoteText =
object.VchWorkNote1 ?? "" +
object.VchWorkNote2 ?? "" +
object.VchWorkNote3 ?? "" +
object.VchWorkNote4 ?? "" +
object.VchWorkNote5 ?? "" +
object.VchWorkNote6 ?? "" +
object.VchWorkNote7 ?? "" +
object.VchWorkNote8 ?? "" +
object.VchWorkNote9 ?? "" +
object.VchWorkNote10 ?? "" +
object.VchWorkNote11 ?? "" +
object.VchWorkNote12 ?? "" +
object.VchWorkNote13 ?? "" +
object.VchWorkNote14 ?? "" +
object.VchWorkNote15 ?? "" +
object.VchWorkNote16 ?? "" +
object.VchWorkNote17 ?? "" +
object.VchWorkNote18 ?? "" +
object.VchWorkNote19 ?? "" +
object.VchWorkNote20 ?? ""
}).ToList();

Resources