Passing parameter to LINQ query - c#

I have a method like below:
public void GetUserIdByCode(string userCode)
{
var query = from u in db.Users
where u.Code == userCode // userCode = "LRAZAK"
select u.Id;
var userId = query.FirstOrDefault(); // userId = 0 :(
}
When I ran the code, I got the default value of 0 assigned to userId meaning the Id was not found.
However, if I changed the userCode with a string like below, I will get the value I want.
public void GetUserIdByCode(string userCode)
{
var query = from u in db.Users
where u.Code == "LRAZAK" // Hard-coded string into the query
select u.Id;
var userId = query.FirstOrDefault(); // userId = 123 Happy days!!
}
My question is why passing the parameter into the LINQ query does not work?
When I stepped into the code, I got the SQL statement like so:
// Does not work...
{SELECT "Extent1"."LOGONNO" AS "LOGONNO"FROM "DEBTORSLIVE"."DEBTORS_LOGONS" "Extent1"WHERE ("Extent1"."LOGONCODE" = :p__linq__0)}
The hard-coded LINQ query (the working one) gives an SQL statement as below:
// Working just fine
{SELECT "Extent1"."LOGONNO" AS "LOGONNO"FROM "DEBTORSLIVE"."DEBTORS_LOGONS" "Extent1"WHERE ('LRAZAK' = "Extent1"."LOGONCODE")}
What would be the solution?

As a work-around, I use Dynamic Linq.
The code below is working for me.
public void GetUserIdByCode(string userCode)
{
string clause = String.Format("Code=\"{0}\"", userCode);
var userId = db.Users
.Where(clause)
.Select(u => u.Id)
.FirstOrDefault();
}
The database query returns an object of User with Code and Id as properties. This is defined in one of my classes.

Here is syntax that will work to pass an argument to a LINQ query.
Not sure how many people will be searching this topic so many years later, but here's a code example that gets the job done:
string cuties = "777";
// string collection
IList<string> stringList = new List<string>() {
"eg. 1",
"ie LAMBDA",
"777"
};
var result = from s in stringList
where (s == cuties)
select s;
foreach (var str in result)
{
Console.WriteLine(str); // Output: "777"
}

Related

'IN' gives empty result - c# and cosmos

I am trying to query the cosmos and the query works. The query looks like
'Select * from c where c.id IN ('123', '456')'.
Now in my c# code, I get empty result. The c# code looks like :
public void GetValue(IEnumerable<string> ids, string s)
{
StringBuilder sb = new();
_ = sb.Append("SELECT t.id FROM t ")
.Append("WHERE t.id IN (#items) ")
.Append("AND t.state != #state");
var queryDefinition = new QueryDefinition(sb.ToString())
.WithParameter("#items", ids)
.WithParameter("#state", s);
var results = GetQueryResults<TableName>(queryDefinition); // Get Empty Result
// Some logic based on results
}
// GetQueryResults query the container and gets the result for the tableName.
SO, I was able to conclude that the 'IN' query syntax is incorrect. Can anyone help me out.
The problem is here:
.Append("WHERE t.id IN (#items) ")
The list cannot be parameterized. One possiblity is to add the list items as separate parameters. There is an example of that here.
EDIT
I found the solution here
var querySpec = new SqlQuerySpec {
QueryText = "SELECT t.Id FROM t WHERE ARRAY_CONTAINS(#Ids, t.Id)",
Parameters = new SqlParameterCollection {
new SqlParameter {
Name = "#Ids",
Value = ids
}
}
}

Linq query Contains method with where condition with case sensitive less search

I am trying get the data which is contains single word with in the word.Like below query.
List<Models.tbluser> memberslist = new List<Models.tbluser>();
var obct = (from memlist in objcontext.tblusers
where memlist.logname.Contains(member)
select new
{
userid = memlist.userid,
logname = memlist.logname,
decription = memlist.description
}).ToList();
foreach (var item in obct)
{
memberslist.Add(new tbluser
{
userid = item.userid,
logname = item.logname,
description = item.decription
});
}
return Json(memberslist);
But here my problem is i need to search with out case sensitive.
For example
If i search with 'a' i need to get data like Admin,Administrator,User Data.
But i am not getting all these because i am searching with Contains() method.Please let me know how can i get all value either the search value is case sensitive less also.
Change your where condition to be:
memlist.logname.ToUpper().Contains(member.ToUpper())
As a side note, you can shorten your query a bit (you don't need to create an intermediary list):
var memberslist = objcontext.tblusers
.Where(x => x.logname.ToUpper().Contains(member.ToUpper())
.AsEnumerable()
.Select(x => new tbluser
{
userid = x.userid,
logname = x.logname,
decription = x.description
})
.ToList();
return Json(memberslist);
You can change them to Lower or Upper Case when checking the condition using ToLower() or ToUpper():
var obct = (from memlist in objcontext.tblusers
where memlist.logname.ToLower().Contains(member.ToLower())
select new
{
userid = memlist.userid,
logname = memlist.logname,
decription = memlist.description
}).ToList();

Combining Tables With Different Data Using Linq in MVC?

I have Two classes Named OfflineOrderLineItem.cs and OnlineOrderLineItem.cs both have diff Order table named offline and Online
In that i want to Combine the two tables data to search and Display the Fields from both tables
How to do that using linq in mvc4 ??? any idea.....
public virtual IPagedList<OnlineOrderLineItem> SearchOrderLineItems(string PoNumber)
{
var query1 = (from ol in _offlineOrderLineItemRepository.Table
select new
{
ol.Name
}).ToList();
var query2 = (from opv in _onlineOrderLineItemRepository.Table
select new
{
opv.Name
}).ToList();
var finalquery = query1.Union(query2);
if (!String.IsNullOrWhiteSpace(Name))
finalquery = finalquery.Where(c => c.Name == Name);
var orderlineitems = finalquery.ToList(); //its not working it throw a error
return new PagedList<OnlineOrderLineItem>(orderlineitems);//error
}
Error
cannot convert from 'System.Collections.Generic.List<AnonymousType#1>'
to 'System.Linq.IQueryable<Nop.Core.Domain.Management.OnlineOrderLineItem>'
to 'System.Linq.IQueryable<Nop.Core.Domain.Management.OnlineOrderLineItem>'
query1 and query2 are lists of an anonymous type with a single property of type string. (I assmume the ol.Name and opv.Name are strings.) Hence finalQuery and orderlineitems are collections of this anonymous as well. By specifying PagedList<T> you require that the collection passed into the constructor is an enumeration of type T. T is OnlineOrderLineItem, but the enumeration passed into the constructor is the anonymous type which is a different type. Result: compiler error.
To solve the problem I suggest that you define a named helper type that you can use to union the two different types OfflineOrderLineItem and OnlineOrderLineItem:
public class OrderLineItemViewModel
{
public int Id { get; set; }
public string PoNumber { get; set; }
public string Name { get; set; }
// maybe more common properties of `OfflineOrderLineItem`
// and `OnlineOrderLineItem`
}
Then your SearchOrderLineItems method should return a paged list of that helper type:
public virtual IPagedList<OrderLineItemViewModel> SearchOrderLineItems(
string PoNumber)
{
var query1 = from ol in _offlineOrderLineItemRepository.Table
select new OrderLineItemViewModel
{
Id = ol.Id,
PoNumber = ol.PoNumber,
Name = ol.Name,
// maybe more properties
};
// don't use ToList here, so that the later Union and filter
// can be executed in the database
var query2 = from opv in _onlineOrderLineItemRepository.Table
select new OrderLineItemViewModel
{
Id = opv.Id,
PoNumber = opv.PoNumber,
Name = opv.Name,
// maybe more properties
};
// don't use ToList here, so that the later Union and filter
// can be executed in the database
var finalquery = query1.Union(query2);
// again no ToList here
if (!string.IsNullOrWhiteSpace(PoNumber))
finalquery = finalquery.Where(c => c.PoNumber == PoNumber);
var orderlineitems = finalquery.ToList(); // DB query runs here
return new PagedList<OrderLineItemViewModel>(orderlineitems);
}
It is important to use ToList only at the very end of the query. Otherwise you would load the whole tables of all OnlineOrderLineItems and all OfflineOrderLineItems into memory and then filter out the items with the given PoNumber in memory which would be a big overhead and performance desaster.
Instead of
var orderlineitems = finalquery.ToList();
Try
var orderlineitems = finalquery.AsQueryable();
From https://github.com/TroyGoode/PagedList/blob/master/src/PagedList/PagedList.cs, PagedList takes a IQueryable<T>
Queryable.AsQueryable<TElement> Method

LINQ to SQL Storing query results in a variable

For example I am searching for a specific persons ID and I want to store that ID to a local variable or instance variable. How do I retrieve Query results and stores them in a int Variable with LINQ to SQL?
Assuming we have this query
from user in dbo.DoctorsName
where doctorsName = "Foo Bar"
select DOC_ID;
You can use FirstOrDefault() like this:
var results = from user in dbo.DoctorsName
where user.doctorsName == "Foo Bar"
select user;
string personName = results.FirstOrDefault().Name;
This should help.
var name = dbo.DoctorsName.Where(item => item.doctorsName = "Foo Bar").Select(item => item.Name).FirstOrDefault();
If there are no records for your condition then using FirstOrDefault() can throw an exception. For this you can try using -
var namelist = dbo.DoctorsName.Where(item => item.doctorsName = "Foo Bar").Select(item => item.Name);
If(namelist.Count() > 0)
var name = namelist.Fisrt();
Similar to this:
var ticketDepartment = from t in dt_tickets.AsEnumerable()
where t.Field<string>("MID") == mid
select new { department = t.Field<string>("Department") };
and now you have your variable in ticketDepartment.department

String.Split in a Linq-To-SQL Query?

I have a database table that contains an nvarchar column like this:
1|12.6|18|19
I have a Business Object that has a Decimal[] property.
My LINQ Query looks like this:
var temp = from r in db.SomeTable select new BusinessObject {
// Other BusinessObject Properties snipped as they are straight 1:1
MeterValues = r.MeterValues.Split('|').Select(Decimal.Parse).ToArray()
};
var result = temp.ToArray();
This throws an NotSupportedException: Method 'System.String[] Split(Char[])' has no supported translation to SQL.
That kinda sucks :) Is there any way I can do this without having to add a string property to the business object or selecting an anonymous type and then iterating through it?
My current "solution" is:
var temp = from r in db.SomeTable select new {
mv = r.MeterValues,
bo = new BusinessObject { // all the other fields }
};
var result = new List<BusinessObject>();
foreach(var t in temp) {
var bo = t.bo;
bo.MeterValues = t.mv.Split('|').Select(Decimal.Parse).ToArray();
result.Add(bo);
}
return result.ToArray(); // The Method returns BusinessObject[]
That's kinda ugly though, with that temporary list.
I've tried adding a let mv = r.MeterValues.Split('|').Select(Decimal.Parse).ToArray() but that essentially leads to the same NotSupportedException.
This is .net 3.5SP1 if that matters.
You need to force the select clause to run on the client by calling .AsEnumerable() first:
var result = db.SomeTable.AsEnumerable().Select(r => new BusinessObject {
...
MeterValues = r.MeterValues.Split('|').Select(Decimal.Parse).ToArray()
}).ToList();
You can't use split, but in this scenario you can do the following:
// Database value is 1|12.6|18|19
string valueToFind = "19";
var temp = from r in db.SomeTable.Where(r => ("|" + r.MeterValues + "|").Contains("|" + valueToFind + "|"));
This code adds outer pipes (|) to the database value on the fly inside the query so you can do start, middle, and end value matches on the string.
For example, the above code looks for "|19|" inside "|1|12.6|18|19|", which is found and valid. This will work for any other valueToFind.
You don't need to use a temporary list:
var query = from r in db.SomeTable
select new
{
r.Id,
r.Name,
r.MeterValues,
...
};
var temp = from x in query.AsEnumerable()
select new BusinessObject
{
Id = x.Id,
Name = x.Name,
MeterValues = x.mv.Split('|').Select(Decimal.Parse).ToArray(),
...
};
return temp.ToArray();
Unfortunately its the IQueryable you are using (Linq to SQL) that is not supporting the Split function.
You are really only left with the IEnumerable (Linq to Objects) support for it in this case. You second code snippet is what you need to do, or something like...
var temp = (from r in db.SomeTable select new {
mv = r.MeterValues,
bo = new BusinessObject { // all the other fields }
}).AsEnumerable().Select(blah, blah) ;

Categories