Unrecognized expression node ArrayIndex using linq with predicate - c#

Hi i have this query...
List<VisitorsVo> lstVisitors = new List<VisitorsVo>();
var predicate = ReturnPredicateForVisitors(p_htVisitor);
if (predicate != null)
{
lstVisitors = (from n in context.TBL_VISITORs.Where(predicate)
select new VisitorsVo
{
VisitId = n.VISIT_ID,
VisitorName = n.VISITOR_NAME,
ResidentDuration = n.ENQUIRY_PATIENT_DURATION.Split(';')[0] + " " + n.ENQUIRY_PATIENT_DURATION.Split(';')[1],
}).ToList();
}
but i am getting Unrecognized expression node ArrayIndex error how can i overcome...
here i am checking condition in where using predicates....

It looks like this is LINQ to Entities, not plain LINQ. Is your context an Entity Framework or LINQ to SQL context?
If so, then LINQ to Entities/SQL will try to translate this expression into SQL, which it cannot do if it contains function calls it doesn't know or that have no SQL equivalent.
My money is on the use of Split(); I'll bet that LINQ to Entities barfs on that.
What you can do is modify your query to get rid of the Split(), and afterward you can query lstVisitors (which is now just an in-memory data structure, it has no link to Entity Framework) and use Split() there.

If you need to split a column that means you can hold that data in two separate columns.
If I were you I'd go to the database design and convert ENQUIRY_PATIENT_DURATION into 2 columns and do it properly. Your code seems very error prone.

Related

An exception occurred with using LINQ method syntax (LINQ to SQL) in C#

I use Linq to Sql and method syntax of Linq in my code to query from database with all tables. And I met an weird exception today, this is the first time error occurred since I started to use L2S.
There are two columns in database table.
And the column of "Status" is mapping to program with an enumeration type: 1(Free), 2(Loan).
。Database table schema as below.
。Define table class
private string Type;
private byte Status;
。Query code
string _qNote = string.Empty;
string _qStatus = string.Empty;
List<DefineTableClass> _List = _dbObj.Table.Select(_obj => _obj)
.Where(_obj =>
(string.IsNullOrWhiteSpace(_qNote) || _obj.Note == _qNote)
&& (string.IsNullOrWhiteSpace(_qStatus) || Convert.ToInt32(_obj.Status) == Convert.ToInt32(_qStatus))
).ToList();
The exception occurred at
Convert.ToInt32(_obj.Status) == Convert.ToInt32(_qStatus)
and I am wondering this line should be passed at
(string.IsNullOrWhiteSpace(_qStatus)
due to _qStatus is Empty and it should not to do the next check.
Improve your query by preparing parameters outside Queryable lambda:
string _qNote = string.Empty;
string _qStatus = string.Empty;
var query = _dbObj.Table.AsQueryable();
if (!string.IsNullOrWhiteSpace(_qNote))
query = query.Where(_obj => _obj.Note == _qNote);
if (!string.IsNullOrWhiteSpace(_qStatus))
{
var byteStatus = Convert.ToByte(_qStatus);
query = query.Where(_obj => _obj.Status == byteStatus);
}
var _List = query.ToList();
It should produce more effective SQL and may avoid unwanted conversions.
I found the similar situations with my question.
L2S will check ALL where conditions, so it must to do (string.IsNullOrWhiteSpace(_qStatus) no matter the front check we think it's should be passed cause it's true.
The better way to write L2S might less use casting in the syntax and like #SvyatoslavDanyliv said, preparing parameters outside Queryable lambda can prevent the weird logic question as mine at this time.
Reference:
Why isn't this short circuit is not working in linq to sql query?
Why isn't this short circuit in lambda working?

Error using EF6 DbFunctions.TruncateTime comparing DateTime

I`m trying to retrieve some data from a data range using the following code:
var rotas = db.X.Where(r => r.DataDaExecucao != null)
.Where(r => System.Data.Entity.DbFunctions.TruncateTime(r.Date.Value) >= System.Data.Entity.DbFunctions.TruncateTime(startDateTime))
.Where(r => System.Data.Entity.DbFunctions.TruncateTime(r.Date.Value) < System.Data.Entity.DbFunctions.TruncateTime(endDateTime))
.Join(db.T, r => r.Id, t => t.X_Id.Value,
(r, t) => new
{
id = r.Id,
start = r.Date.Value.ToString("s"),
end = r.Date.Value.AddDays(1).ToString("s"),
title = t.Z.Name,
allday = false
}).ToList();
"Date" properties are Nullable< DateTime>.
I`m getting the following error message:
LINQ to Entities does not recognize the method 'System.String ToString(System.String)' method, and this method cannot be translated into a store expression.
Exception Details: System.NotSupportedException: LINQ to Entities does not recognize the method 'System.String ToString(System.String)' method, and this method cannot be translated into a store expression.
Also, I don`t have the System.Data.Entity.dll assembly referenced in my csproj.
Ideas?
Thank you, in advance.
You can change the anonymous type using SqlFunctions where it will also generate the sql query.
In your case you use ToString("s"), meaning you want to get the date part of second that can be replaced by SqlFunctions::DatePart. And Date::AddDays can be replaced by SqlFunctions::DateAdd.
new
{
id = r.Id,
start = SqlFunctions.DatePart("s", r.Date),
end = SqlFunctions.DatePart("s", SqlFunctions.DateAdd("d", 1, r.Date)),
title = t.Z.Name,
allday = false
}
DateTime.ToString() cannot be converted into a SQL statement by LINQ to Entities. e.g.
start = r.Date.Value.ToString("s")
The thing to do is call .ToList() to force the LINQ to Entities to execute its underlying SQL query. That way the remainder of the LINQ statement will use LINQ to Objects (in-memory query of a collection of objects).
In your case I would break the LINQ statement into 2 parts:
The first half which queries the DB with LINQ to Entities SQL generation, and calls .ToList() at the end
The second half which runs LINQ to Objects to do the in-memory part.

Linq to entities - Lambda - Concatenate strings

I would like to concatenate a string using lambda to compare that concatenated value against a certain condition.
Invoices = Invoices.Where(f => ((string)f.invoice_prefix + String.Format("{0:0000}", Convert.ToInt32(f.invoice_number))).ToLower().Equals(condition7));
But I get an error message :
The name 'f' does not exist in the current context
Tried several String.Format and String.Concat variants like
Invoices = Invoices.Where(f => (String.Format("{0}{1}",f.invoice_prefix,String.Format("{0:0000}", Convert.ToInt32(f.invoice_number)))).ToLower().Equals(condition7));
but no success... Can somebody help me with the syntax?
Thanks in advance!
Linq to Entities doesn't understand all of the .NET framework methods.
In order to run this as a SQL statement on the database, you need to only use operators that can be converted to SQL. That means you need to re-write your predicate using primitive data types.
So something like this:
string prefixCondition = ...
int invoiceNumberCondition = ...
Invoices.Where( f =>
f.invoice_prefix == prefixCondition
&&
f.invoice_number == invoiceNumberCondition
)
I recommend using LinqPad to test with, as it shows you the generated SQL statement.

C# get data from database

I need to enhance a function of C# code. I am new to C# but I have strong java background.
My job is to write a new query, like JDBC, to get data from database.
In the method below, I didn't see any SQL query.
what does this line mean ? is this similar to Hibernate hql ?
from p in Session.Query<MyObject>() select p
Thanks
code:
public IPagingList<MyObject> ReadMyObjectItems(int start, int limit, IList<Filter> filters)
{
var criteria = Session.CreateCriteria<MyObject>();
if (limit != -1)
{
criteria.SetMaxResults(limit);
criteria.SetFirstResult(start);
}
if (filters != null)
{
foreach (var filter in filters)
{
criteria.Add(Restrictions.InsensitiveLike(filter.Field, "%" + filter.Value + "%"));
}
}
IList<MyObject> report = criteria.List<MyObject>();
int total = (from p in Session.Query<MyObject>() select p).Count();
var pagedResults = new PagingList<MyObject> { List = report, Total = total };
return pagedResults;
}
(from p in Session.Query<MyObject>() select p).Count();
We are simply getting a count of all the objects.
Refactor this to
Session.Query<MyObject>().Count(). It's easier to read and in this case LINQ is unnecessary.
It's Linq syntax. A powerful form of querying incorporated into .Net and different .Net frameworks.
In your case it seems you are using NHibernate and that line is using NHibernate Linq. (But the surrounding code is using Criteria.)
For composing queries in NHibernate you have the options of using
Linq
HQL
Criteria
which all have different pros and cons.
Either will be translated into SQL by NHibernate. The actual result will be fetched when you try to access it such as for instance reading an item in the result or converting the result to a List etc.
It seems that project is using an ORM like NHibernate. You can get more details here : http://nhibernate.info

LINQ To SQL exception: Local sequence cannot be used in LINQ to SQL implementation

everybody.
I know, that this topic has been discussed yet. But, unfortunately, I didn't find any solution in existing answers.So, I have the next code:
public List<List<string>> DataTableParser(IQueryable<T> queriable)
{
//I missed the unnecessary code
return queriable.Select(SelectProperties).ToList();
//I missed the unnecessary code
}
private Expression<Func<T, List<string>>> SelectProperties
{
get
{
var properties = typeof(T).GetProperties();
//
return value => properties.Select
(
// empty string is the default property value
prop => (prop.GetValue(value, null) ?? string.Empty).ToString()
)
.ToList();
}
}
So, in the method DataTableParser I have the exception with the next message:
"Local sequence cannot be used in LINQ to SQL implementation of query operators except the Contains() operator".
I don't use in my query "where" part. So I can't imagine how to use "Contains" operator. And I can't understand the reason of the exception.
Does anyone have any ideas? I will appreciate any help. Thanks.
try using
return queriable.AsEnumerable().Select(SelectProperties).ToList();
this evaluates the sql of the queriable first and creates in memory objects that will then be processable by reflection
linq to sql only knows how to translate an expression into sql. there is a limited number of expressions that are translatable to sql. the properties that represent your columns are translatable to sql.
queriable.Select(x=>x.MyColumn);
//is translatable to sql when there is a column that is named MyColumn in your table
queriable.Where(x=>x.MyColumn.Contains("X"))
//is translatable to sql as "...where MyColumn like '%X%' ..."
queriable.Select(x=> new { x.MyColumn, x.AnotherColumn})
//is translatable to sql for selecting multiple columns
queriable.Select(SelectProperties)
//is not translatable to sql because it does not return an expression that selects a single value, and its not an expression that returns a new object.
How do you intend to use this method?

Categories

Resources