How to append sql to Entity Framework query - sql

How to append raw sql e.g. condition to entity framework linq query?
I'm open to all suggestions so it's not mandatory to append it to linq query main point is to e.g. filter by adding some custom sql to query overall.

Using IQueryable we can append the condition on the Linq to entity query.
private IQueryable<Customer> FilterList(IQueryable<Customer> customer, List<string> filter, string filterValue)
{
IQueryable<Customer> query = new List<Customer>().AsQueryable();
if (filter == null || string.IsNullOrEmpty(filterValue))
{
return customer;
}
var filterLower = filter.First().ToLower();
filterValue = filterValue.ToLower();
if (filterLower.Contains("retail") || (filterLower.Contains("distributor"))
{
return customer.Where(x => (!string.IsNullOrEmpty(x.Retail) && x.Retail.Contains(filterValue)) || (!string.IsNullOrEmpty(x.Distributor) && x.Distributor.Contains(filterValue)));
}
if (filterLower.Contains("retail"))
{
query = customer.Where( x=> !string.IsNullOrEmpty(x.Distributor) && x.Distributor.Contains(filterValue));
}
if (filterLower.Contains("distributor"))
{
query = customer.Where(x => !string.IsNullOrEmpty(x.Retail) && x.Retail.Contains(filterValue)).Union(query);
}
return query;
}

Related

How to combine IQueryable records in .net Core 6 Web API

I'm using .net Core 6 web API, and I've this case where I need to loop through multiple object, and each has a IQueryable result.
Then all results need to be grouped in one query. Finally the the result will be sent as paginated list.
Here's more details in the code, I will get list of ObjectA from db:
var query = _context.ObjectA.AsQueryable();
Now I need to get list of User. For some reason the users will have multiple records with their username, so each record represent a role:
var rolesFromDb = await _context.User.Include(x => x.Role).Where(x => x.Username == "user").ToListAsync();
Now I need to loop through dynamic roles and filter the query. I have 2 (or more) conditions, the the code will look like this:
if (rolesFromDb.Count != 0)
{
var result = new List<ObjectA>();
foreach (var item in rolesFromDb)
{
if (item.Role.Level == 1)
{
var condition1 = query.Where(x => x.Level == 1);
result.AddRange(condition1);
continue;
}
if (item.Role.Level == 2)
{
var condition2 = query.Where(x => x.Level == 2);
result.AddRange(condition2);
continue;
}
}
query = result; // I need to do something like this, this is not the way to do ofc
}
After this loop, I've a search filter that depends on this query.
In general, my main issue is I'm not able to make query = all filtered queries.
Thank you.

Easiest way to check record is exist or not in Linq to Entity Query

in store procedure we can check record is exist or not using following query for fast performance
if EXISTS ( Select 1 from Table_Name where id=#id )
But what about Linq query.
right now i have to store whole data in object like this
UserDetail _U=db.UserDetails.where(x=>x.id==1).FirstOrDefault();
Any Solution?
Use Linq's Any ie bool exist = db.UserDetails.Any(x => x.id == 1);
if(db.UserDetails.Any(x => x.id == 1)) {
var userDetail = db.UserDetails.FirstOrDefault(x => x.id == 1);
}
bool exist = db.UserDetails.Where(x=>x.id==1).Any();
if(exist){
//your-code
}else{
//your-code
}
Just check
if(_U == null)
This way you will get what you want in single query and you not need to execute addition query like
db.UserDetails.Any(x => x.id == 1)
I think, it does not require to fire two query. It can be accomplish by single query.
UserDetails objUserDetails =db.UserDetails.FirstOrDefault(x => x.id == 1);
if(objUserDetails==null)
{
// Do something
}
else
{
// do something with objUserDetails
}
var qry = db.User_Detail.Where(x => x.User_Id == 1).FirstOrDefault();
if(qry !=null)
{
// Do something
}
else
{
return false;
}
Try This...

Entity Framework Union And Paging

I am getting the result query by running two queries and joining them with union clause. I have to use paging but I need results as inserted line. I don't want to order it again. But when I use paging I have to use order by clause. how can I get results with natural order.
var prodFullTextQuery = _db.Products
.Where(x => !x.IsDeleted
&& x.ProdStatusValue == (int)ProdStatus.Active
&& (x.ProdName.Contains(searchText)
|| x.Keywords.Contains(searchText)
|| x.ManufacturerCode.StartsWith(searchText)
));
IQueryable<Product> prodQuery;
prodQuery = _db.Products.Where(x => !x.IsDeleted
&& x.ProdStatusValue == (int)ProdStatus.Active
&& x.VariantMainProdId == x.ProdId);
foreach (var s in searchText.Split(' '))
{
var temp = s;
prodQuery = prodQuery.Where(x => x.Keywords.Contains(temp));
}
prodFullTextQuery = prodFullTextQuery.Union(prodQuery)
//i need here by the order in which rows are inserted
var results= prodFullTextQuery
.OrderBy(x=>x.OrderId) //i don't want this
.Skip(prodCountPerPage * pageNumber)
.Take(prodCountPerPage)
.ToList()

working with option of $query in yii2

i want use where for $query.
foreach ($oppId as $o) {
$id = $o['opportunity_id'];
$query->Where("id=$id");
}
When I use this. All items shown
$query->orWhere("id=$id");
i need get this query :
SELECT * FROM `opportunity` WHERE id =27 or id =28
this is all of my function :
public function actionShow($type = 0, $city = 0, $client = 0) {
$query = (new \yii\db\Query())->select(['*'])->from('opportunity ')->innerJoin('profile_details', 'opportunity.user_id=profile_details.user_id')->orderBy('id desc');
$query->Where('id !=-1');
if (isset($_REQUEST['type'])) {
$type = $_REQUEST['type'];
if ($type != 0) {
$query->andWhere("project_type_id=$type");
}
}
if (isset($_REQUEST['city'])) {
$city = $_REQUEST['city'];
if ($city != 0) {
$query->andWhere("state_id=$city");
}
}
if (isset($_REQUEST['client'])) {
$client = $_REQUEST['client'];
if ($client != 0) {
$oppId = \app\models\OpportunityControl::find()
->where('project_type_id = :project_type_id', [':project_type_id' => $client])
->all();
foreach ($oppId as $o) {
$id = $o['opportunity_id'];
$query->orWhere("id=$id");
}
}
}
You very much do not want to use strings to add to the query under any circumstances as that is ripe for SQL injection. I'd format it like this:
...
$params = [];
foreach ($oppId as $o) {
$params[] = $o->opportunity_id;
}
$query->andWhere(['in', 'id', $params]);
...
You should also adjust your other query params so that you are not passing variables into SQL via a string.
if (isset($_REQUEST['type'])) {
$type = $_REQUEST['type'];
if ($type != 0) {
$query->andWhere(['project_type_id' => $type]);
}
}
if (isset($_REQUEST['city'])) {
$city = $_REQUEST['city'];
if ($city != 0) {
$query->andWhere(['state_id' => $city]);
}
}
See the Yii2 guide on using variables in queries for what you are trying to avoid here. Specifically:
Do NOT embed variables directly in the condition like the following, especially if the variable values come from end user inputs, because this will make your application subject to SQL injection attacks.
// Dangerous! Do NOT do this unless you are very certain $status must be an integer.
$query->where("status=$status");
I do it with Arrays
$query->where(['or',['id'=>27],['id'=>28]]);
But in your case save all ids in a Array is not possible,I do it with string inside foreach
$StringWhere='';
$LastElement = end($oppId);
foreach ($oppId as $o)
{
$id = $o['opportunity_id'];
$StringWhere.=' id='.$id;
if($o!=$LastElement)
{
$StringWhere.=' or ';
}
}
$query->where($StringWhere);
$query->where(['or',['id'=>27],['id'=>28]]);
I use this and it works perfectly as mentioned by metola. :)

WPF application Linq to sql getting data

I'm making a WPF application with a datagrid that displays some sql data.
Now i'm making a search field but that doesn't seem to work:
Contactpersoon is an nvarchar
bedrijf is an nvarchar
but
LeverancierPK is an INT
How can I combinate that in my search?
If i convert LeverancierPK to string, then I can use Contains but that gives me an error
//Inisiatie
PRCEntities vPRCEntities = new PRCEntities();
var vFound = from a in vPRCEntities.tblLeveranciers
where ((((a.LeverancierPK).ToString()).Contains(vWoord)) ||
(a.Contactpersoon.Contains(vWoord)) ||
(a.Bedrijf.Contains(vWoord)))
orderby a.LeverancierPK
select a;
myDataGrid_Leveranciers.ItemsSource = vFound;
Thanks
If you don't care about pulling all records back from the DB (which in your answer you pulled everything back), then you can just do a .ToList() before the where clause.
var vFound = vPRCEntities.tblLeveranciers.ToList()
.Where(a => a.LeverancierPK.ToString().Contains(vWoord)) ||
a.Contactpersoon.Contains(vWoord) ||
a.Bedrijf.Contains(vWoord))
.OrderBy(a.LeverancierPK);
This code can do what I was looking for but I think it could be alot shorter.
PRCEntities vPRCEntities = new PRCEntities();
var vFound = from a in vPRCEntities.tblLeveranciers
orderby a.LeverancierPK
select a;
myDataGrid_Leveranciers.ItemsSource = null;
myDataGrid_Leveranciers.Items.Clear();
foreach (var item in vFound)
{
if (item.Bedrijf.Contains(vWoord))
{
myDataGrid_Leveranciers.Items.Add(item);
}
else
{
if (item.LeverancierPK.ToString().Contains(vWoord))
{
myDataGrid_Leveranciers.Items.Add(item);
}
else
{
if (item.Contactpersoon != null)
{
if (item.Contactpersoon.Contains(vWoord))
{
myDataGrid_Leveranciers.Items.Add(item);
}
}
}
}
}