I am using LINQ to select a list based on a particular condition. The attribute value is stored in byte array, which is later encrypted while storing in the database table. I want to using this attribute in my SELECT LINQ query now, but it is throwing the following exception when I try to:
LINQ to Entities does not recognize the method 'Byte[] GetBytes(System.String)' method, and this method cannot be translated into a store expression.
This is the code that I using:
var result = (from history in context.Histories
where history.ID == Id &
(history.Salary != null || history.Salary != Encoding.ASCII.GetBytes("0"))
select (DateTime?)history.Date).Max();
return result;
I want to select the date from the history table, of those id's whose salary is either not equal to null or 0. How can I change this?
Just get the bytes first :
var bytes = Encoding.ASCII.GetBytes("0");
var result = (from history in context.Histories
where history.ID == Id &
(history.Salary != null || history.Salary != bytes)
select (DateTime?)history.Date).Max();
return result;
Change your code to:
var bytes = Encoding.ASCII.GetBytes("0");
var result = (from history in context.Histories
where history.ID == Id &
(history.Salary != null || history.Salary != bytes)
select (DateTime?)history.Date).Max();
return result;
LINQ can't evaluate your GetBytes when it translates your query to SQL
Related
My model has:
Several DeviceStatus attached to one mandatory Device
SeveralDevice attached to one mandatory Panel
When I query DeviceStatus, I need to have Device and Panel attached to it in the query result.
... DeviceStatus.Device is null in the query result.
Here is the Linq Query:
using (var actiContext = new ActigraphyContext())
{
var todayStatus =
from s in actiContext.DeviceStatus.Include(s1 => s1.Device.Panel)
where DbFunctions.TruncateTime(s.TimeStamp) == DbFunctions.TruncateTime( DateTimeOffset.Now)
&& s.Device.Panel.Mac == mac
&& (s.Device.Ty == 4 || s.Device.Ty == 9)
select s;
// var tempList = todayStatus.toList();
var todayLastStatus =
from s in todayStatus.Include(s1 => s1.Device.Panel)
let lastTimeStamp = todayStatus.Max(s1 => s1.TimeStamp)
where s.TimeStamp == lastTimeStamp
select s;
var requestResult = todayLastStatus.FirstOrDefault();
return requestResult;
}
If I uncomment the line // var tempList = todayStatus.toList();, where tempList is not used, it works: requestResult.Device is set!
But the bad side is todayStatus.toList triggers a request that brings a huge amount of data.
So how to get the DeviceStatus with its relative objects ?
Note: the database behind is SQL Server 2012
When you call an Include() over a LINQ query, it performs Eagerly Loading.
As documented in MSDN:
Eager loading is the process whereby a query for one type of entity also loads related entities as part of the query. Eager loading is achieved by use of the Include method.
When the entity is read, related data is retrieved along with it. This typically results in a single join query that retrieves all of the data that's needed. You specify eager loading by using the Include method.
So you need to call the .toList() to complete the query execution.
Since the data is huge, you can pickup relative specific columns as per your requirement by using the Select clause.
var todayStatus =
from s in actiContext.DeviceStatus
.Include(s1 => s1.Device.Panel.Select(d => new
{
d.DeviceId,
d.DeviceName,
d.PanelID
}))
where DbFunctions.TruncateTime(s.TimeStamp) == DbFunctions.TruncateTime( DateTimeOffset.Now)
&& s.Device.Panel.Mac == mac
&& (s.Device.Ty == 4 || s.Device.Ty == 9)
select s;
var tempList = todayStatus.toList();
The query doesn't actually run until you do a call like ToList(), which is why uncommenting that line works. If the query is bringing back too much data, then you need to change the query to narrow down the amount of data you're bringing back.
Ok this request is a more simple way to achieve this:
using (var actiContext = new ActigraphyContext())
{
var todayLastStatus =
from s in actiContext.DeviceStatus.Include(s1 => s1.Device.Panel)
where DbFunctions.TruncateTime(s.TimeStamp) == DbFunctions.TruncateTime( DateTimeOffset.Now)
&& s.Device.Panel.Mac == mac
&& (s.Device.Ty == 4 || s.Device.Ty == 9)
orderby s.TimeStamp descending
select s;
var requestResult = todayLastStatus.Take(1).FirstOrDefault();
return requestResult;
}
But the question remains: why didn't I get the relative object in my first request ?
I am using the following LINQ to Entities code for getting data from a database table named Stocks:
IEnumerable<DrugInfoViewModel> Info = from a in db.Stocks.Where(
r => r.SiteID == SiteID
&& r.MachineID == MachineID
&& EntityFunctions.TruncateTime(r.ExpiryDate) <= ExpiryDate)
select new DrugInfoViewModel()
{
ItemName = a.DrugBrand.Name,
ItemBatchNo = a.BatchNo,
ItemExpiryDate = (a.ExpiryDate == null ? null :
Convert.ToDateTime(a.ExpiryDate).ToString("MM/dd/yyyy")),
Quantity = (int?)a.Qty
};
Here, ItemExpiryDate is a string field and a.ExpiryDate is a nullable datetime field in the table. When I run this code I am getting this error:
LINQ to Entities does not recognize the method 'System.String ToString(System.String)' method, and this method cannot be translated into a store expression.
This same line of code works properly in another page. Why is this happening?
Just add ToList() or ToArray() method after Where(). This will fetch filtered objects to your memory and you will be able to call ToString(). Please, make sure that you call ToList() after filtering to avoid fetching all of the records from the table.
IEnumerable<DrugInfoViewModel> Info = from a in db.Stocks.Where(
r => r.SiteID == SiteID
&& r.MachineID == MachineID
&& EntityFunctions.TruncateTime(r.ExpiryDate) <= ExpiryDate)
.ToList()
select new DrugInfoViewModel()
{
ItemName = a.DrugBrand.Name,
ItemBatchNo = a.BatchNo,
ItemExpiryDate = (a.ExpiryDate == null ? null :
Convert.ToDateTime(a.ExpiryDate).ToString("MM/dd/yyyy")),
Quantity = (int?)a.Qty
};
This happens because the LINQ expression is evaluated on the server side i.e. inside SQL Server and there the function ToString() is not available.
As suggested in the comments already: Get a DateTime, format on the client side.
Using T-SQL in SQL Server Management Studio this query returns exactly what I am expecting
SELECT * FROM ZipCodeTerritory WHERE ZipCode IS NULL and StateCode = 'WA'
However... the following Linq query returns no results. I've checked the connection string and I have verified I'm connecting to the database. Using a value for the cleanZip variable will return a list. Using a null value, however, never returns anything.
string cleanZip = (item.ToUpper().Equals("NULL") ? null : item.Trim());
var zipCodes = (from z in db.ZipCodeTerritory
where z.ZipCode.Equals(cleanZip) && z.StateCode.Equals(searchState)
select z).ToList();
Changed the query to the following and it is working now.
var zipCodes = (from z in db.ZipCodeTerritory
where (cleanZip == null ? z.ZipCode.Equals(null) : z.ZipCode.Equals(cleanZip)) && z.StateCode.Equals(searchState)
select z).ToList();
Currently, i have a table with the data Fruits, grade and price. The grade available in my table are A , B and C. Please look at the code snippet. As what you can see, i put D in the where filter. I suppose the query will be null. But after i run the code, the program prompt the "Not Null? WTH?". So, may i know whats in the query and how to detect the D if it's not in the table?
p/s: i'm newbie
C# code snippet:
var query = (from p in db
where p.grade == "D"
select p.price).ToArray();
if (query == null)
System.Console.WriteLine("You get Null in the query");
else if (query != null)
System.Console.WriteLine("Not Null? WTH?");
Since you are doing ToArray, it will never be null. You may check the length.
if(query.Length <= 0)
Or even better if you do:
var query = (from p in db
where p.grade == "D"
select p.price).Count();
if(query > 0)
or
var ifItemExist = (from p in db
where p.grade == "D"
select p.price).Any();
Or shorter:
var ifItemExist = db.Any(p=> p.grade == "D");
You don't get null because this method will still return an array. The array will be empty, but the array will not be null. (This is in fact why null exists... it is to differentiate between a "zero" value and the absence of a value.
If you want to test if there are any elements in the result you can use:
if (query.Any())
Actually, it is not null, it's returning an empty array which is different from null.
alternately, you can do this,
int query = (from p in db
where p.grade == "D"
select p.price).Count();
if (query > 0)
{
System.Console.WriteLine("Found");
}
else
{
System.Console.WriteLine("Not Found");
}
I have the following linq query:
var solicitudes = from s in dbContext.Menores
select s.Solicitud.fiExpEmpleado;
The query results are 41 employees' Ids. My question is, how can I compare these 41 elements against the value of a textbox so that i can restrict user registration (if the ID of the textbox matches with one of the query result the registration is denied)?
Hope your help.
You can write a query that checks whether the value exists:
if (dbContext.Menores.Any(s => s.Solicitud.fiExpEmpleado == someValue))
string text = textbox.Text.Trim();
var solicitudes = (from s in dbContext.Menores
where s.FieldToCheck == text
select s.Solicitud.fiExpEmpleado).FirstOrDefault();
if (solicitudes != null)
{
//Deny
}
If solicitudes is being returned as a list of ints you could just to:
int employeeId = Convert.ToInt32(txtMyTextBox.Text);
bool isValidEmployeeId = solicitudes.Any(employeeId);
You don't have to compare all values, just create linq query which query for the value of the textbox, and then count use count method,if count is greater then zero, it means it exits,and you can then deny the user.
Here you go.
if (dbContext.Menores.Exists(x => x.FieldToCheck == text))
{
//deny
}