Dynamically build IQueryable OR Statement - c#

I am trying to dynamically build an IQueryable that will test to see if a number of strings exists in the description.
using SQL this can be easily achieved by having multiple OR statements.
but how can i do this using LINQ?
here is my code thus far...
List<string> keywords = new List<string>() { "BMW", "M3" };
IQueryable<AuctionVehicle> Results =
from a in DBContext.tbl_Auction
join v in DBContext.tbl_Vehicle on a.VehicleID equals v.VehicleID
where v.Fuel.Equals(Fuel)
&& v.Transmission.Equals(Transmission)
&& a.EndDate < DateTime.Now
select new AuctionVehicle()
{
DB_Auction = a,
DB_Vehicle = v
};
// Keywords
if (keywords.Count == 1)
{
Results = Results.Where(x => x.DB_Auction.Description.Contains(keywords[0]));
}
else if (keywords.Count > 1)
{
// ****************************
// How can i add multiple OR statements??
// ****************************
Results = Results.Where(x => x.DB_Auction.Description.Contains(keywords[0]));
foreach (string keyword in keywords)
{
Results = Results.Where(x => x.DB_Auction.Description.Contains(keyword));
}
}
return Results;

You can replace:
if (keywords.Count == 1)
{
Results = Results.Where(x => x.DB_Auction.Description.Contains(keywords[0]));
}
else if (keywords.Count > 1)
{
Results = Results.Where(x => x.DB_Auction.Description.Contains(keywords[0]));
foreach (string keyword in keywords)
{
Results = Results.Where(x => x.DB_Auction.Description.Contains(keyword));
}
}
by
Results = Results.Where(x => keywords.Any(y=>x.DB_Auction.Description.Contains(y)));
So, eventually you may want to add this in you LINQ expression:
where keywords.Any(x=>a.Description.Contains(x))

Related

Linq - Loop through list of strings and add results to var variable

I have my code sample below.
List<string> userIds = userAppService.GetUserIds()
.Where(usr => usr.Status == "Active")
.Select(u => u.User_Id)
.ToList();
Now i would like loop through list of above UserId's and add the result to var variable.
foreach(string str in userIds)
{
var result = SLSDBContext.USER_HISTORY
.Where(i => i.UserId == str)
.Select(x => new
{
x.UserId,
x.LogCount,
x.IsRegistered
});
return this.Json(result)
}
The problem with above is i will not be able to access 'result' variale outside of foreach block.. If i am trying yo declare 'result' variable before foreach block i am not able to assign the type to it.
any better way to get the desired result ?
I tried using Any() operator in Linq but i am not able to get the desired result.
var result = SLSDBContext.USER_HISTORY
.Where(i => i.UserId.Contains(userIds))
.Select(x => new
{
x.UserId,
x.LogCount,
x.IsRegistered
});
You could use a Join:
var activeUsers = userAppService.GetUserIds()
.Where(usr => usr.Status == "Active");
var result = from uh in SLSDBContext.USER_HISTORY
join au in activeUsers
on uh.UserId equals au.User_Id
select new {
uh.UserId,
uh.LogCount,
uh.IsRegistered
};
return this.Json(result.ToList());
you can initialize the result before loop and use Concat method.
var result = Enumerable.Empty<USER_HISTORY>();
foreach(string str in userIds)
{
result = result.Concat(SLSDBContext.USER_HISTORY.Where(i => i.UserId == str).Select(x => new {
x.UserId,
x.LogCount,
x.IsRegistered
}));
}
return this.Json(result);

C# LINQ How to find matching item from one list in another list and check for the property in the other list

I would like to loop through a list of item,
find the matching record in another list and
check a property of that item in the new list is enabled/disabled.
if false, break the looping.
Here is my code.
var isDataPresent = true;
foreach (var item in listA)
{
var dataPresent = listB
.FirstOrDefault(x => x.Id == item.Id &&
x.DistributionType == item.DistributionType)
?.IsDataPresent;
if (!dataPresent.GetValueOrDefault())
{
isDataPresent = false;
break;
}
}
return isDataPresent;
Is there a faster/better way to achieve this.
My updated code with JOIN:
var result = listA.Join(listB,
dt => new { dt.Id, dt.DistributionType },
dp => new { dp.Id, dp.DistributionType },
(distType, dataPresent) => new
{
distType.Id,
distType.DistributionType,
dataPresent.IsDataPresent
});
if(result.Any(x => x.IsDataPresent == false))
{
isDataPresent = false;
}
you can change your use of FirstOrDefault() to Any()
that way, you don't need to make other checks and you only need one variable.
var isDataPresent = true;
foreach (var item in listA)
{
isDataPresent = listB.Any(x => x.Id == item.Id &&
x.DistributionType == item.DistributionType && x.IsDataPresent);
if (!isDataPresent)
break;
}
return isDataPresent;
Try with Any like below.
var isDataPresent = !listA.Any(item => !listB
.FirstOrDefault(x => x.Id == item.Id && x.DistributionType == item.DistributionType)
?.IsDataPresent.GetValueOrDefault());
my approach would be .Count()
var countOfA = listA.Count();
var countOfAWithB = listA.Count(a=> listB.Any(b => a.Id == b.Id &&
a.DistributionType == b.DistributionType));
return countOfA == countOfAWithB;
You can achieve by join:
var res = (from dp in dataPresent
from la in listA
where dp.DistributionType == la.DistributionType
select new {
la.isDataPresent }
).ToList()
and there are better solution then join

How do I create and populate a dynamic object using a dynamically built lambda expression

I'm trying to create and populate a dynamic object from a dataset that is only known at run time. In the code below, I create my IEnumerable results from my dataset with some known fields (ID, Primary Data, DisplayOrder, IsActive) and one user-define field (Phone Number) which I won't know at design time, and therefore must be built dynamically. The code below works, but only because I've hard-coded the dynamic field Phone Number. How do I build the Lambda expression dynamically to handle those fields only known at runtime. I want the equivalent of
string fieldName = 'PhoneNumber = ';
string fieldSource = 'pd.tbList_DataText';
string expression = 'pd=>new { ID = pd.ID, PrimaryData=pd.PrimaryData';
expression += fieldName;
expression += FieldSource;
expression += '.Where(ld => ld.DataRowID == pd.ID && ld.ListColumnID == 1).Select(ld => ld.DataField).DefaultIfEmpty("").First()})';
var results = primaryData.Select(expression);
So how do I make that work? Thanks
// Get base Data
IEnumerable<tbList_Data> primaryData = await _tbList_DataRepository.GetAsync(ld => ld.ListID == listId && (ld.IsActive == includeInactive ? ld.IsActive : true));
// Get Final Results
var results = primaryData.Select(pd => new {
Id = pd.ID,
PrimaryData = pd.PrimaryData,
PhoneNumber = pd.tbList_DataText.Where(ld => ld.DataRowID == pd.ID && ld.ListColumnID == 1).Select(ld => ld.DataField).DefaultIfEmpty("").First()
});
I see several options.
1) Tuple
var results = primaryData.Select(pd => new {
Id = pd.ID,
PrimaryData = pd.PrimaryData,
Extra = Tuple.Create("PhoneNumber", pd.tbList_DataText.Where(ld => ld.DataRowID == pd.ID && ld.ListColumnID == 1).Select(ld => ld.DataField).DefaultIfEmpty("").First())
});
// How to access:
foreach (var result in results)
{
Console.WriteLine(result.Id);
Console.WriteLine(result.PrimaryData);
Console.WriteLine(result.Extra.Item1);
Console.WriteLine(result.Extra.Item2);
}
2) Dictionary
// Using C# 6 notation
var results = primaryData.Select(pd => new Dictionary<string, object>{
["Id"] = pd.ID,
["PrimaryData"] = pd.PrimaryData,
["PhoneNumber"] = pd.tbList_DataText.Where(ld => ld.DataRowID == pd.ID && ld.ListColumnID == 1).Select(ld => ld.DataField).DefaultIfEmpty("").First()
});
// Using C# 5 notation
var results = primaryData.Select(pd => new Dictionary<string, object>{
{"Id", pd.ID},
{"PrimaryData", pd.PrimaryData},
{"PhoneNumber", pd.tbList_DataText.Where(ld => ld.DataRowID == pd.ID && ld.ListColumnID == 1).Select(ld => ld.DataField).DefaultIfEmpty("").First()}
});
// How to access:
foreach(var result in results)
{
Console.WriteLine(result["Id"]);
Console.WriteLine(result["PrimaryData"]);
Console.WriteLine(result["PhoneNumber"]);
}
3) Dynamic
var results = primaryData.Select(pd => {
dynamic result = new System.Dynamic.ExpandoObject();
result.Id = pd.ID;
result.PrimaryData = pd.PrimaryData;
// Choose one of the following. Since you only "PhoneNumber" at runtime, probably the second one.
result.PhoneNumber = pd.tbList_DataText.Where(ld => ld.DataRowID == pd.ID && ld.ListColumnID == 1).Select(ld => ld.DataField).DefaultIfEmpty("").First();
((IDictionary<string, object>)result).Add("PhoneNumber", pd.tbList_DataText.Where(ld => ld.DataRowID == pd.ID && ld.ListColumnID == 1).Select(ld => ld.DataField).DefaultIfEmpty("").First());
return result;
});
// How to access:
foreach(var result in results)
{
Console.WriteLine(result.Id);
Console.WriteLine(result.PrimaryData);
// Both work, independently how you created them
Console.WriteLine(result.PhoneNumber);
Console.WriteLine(((IDictionary<string, object>)result)["PhoneNumber"]);
}
EDIT: just realized from question that the field source should be dynamic as well. So, in the above code, replace any occurrence of pb.tbList_DataText by:
((IEnumerable<X>)pb.GetType().GetField("tbList_DataText").GetValue(pb))
Where X should be the type of ld. But carefull! This cast can potentially fail.
Also, if you want a property instead of a field, just use GetProperty instead of GetField.

I need Linq to sql queries with join and count

i need to count how many singles of one matchmaker in tbluserregistration table.
i use following code,in this code if codition for filtering grid record.
please replay me fastly.
private IQueryable chanims
{
get
{
EntitiesModelMX dbContext = new EntitiesModelMX();
//var query = from p in dbContext.TblShadChanims
// where p.Confirmed == true || p.Status != null
// orderby p.ShadChanimID descending
// select p;
var query = from p in dbContext.TblShadChanims
join u in dbContext.TblUserRegistrations
on p.ShadChanimID equals u.ShadChanID into usercount
orderby p.ShadChanimID descending
select new
{
p,
Singles = usercount.Where(usr => usr.ShadChanID !=0).Count()
};
if (txtFirstNameFilter.Text.Trim().Length > 0)
{
query = (IOrderedQueryable<MainDataMX.TblShadChanim>)query.Where(p => p.p.FirstName.Contains(txtFirstNameFilter.Text.Trim()));
}
if (txtLastNameFilter.Text.Trim().Length > 0)
{
query = (IOrderedQueryable<MainDataMX.TblShadChanim>)query.Where(p => p.LastName.Contains(txtLastNameFilter.Text.Trim()));
}
if (txtPhoneFilter.Text.Trim().Length > 0)
{
query = (IOrderedQueryable<MainDataMX.TblShadChanim>)query.Where(p => p.Phone1.Contains(txtPhoneFilter.Text.Trim()));
}
if (!ddlStatus.SelectedValue.Equals("ALL"))
{
query = (IOrderedQueryable<MainDataMX.TblShadChanim>)query.Where(p => p.Status == (int?)int.Parse(ddlStatus.SelectedValue));
}
if (txtEmailFilter.Text.Trim().Length > 0)
{
query = (IOrderedQueryable<MainDataMX.TblShadChanim>)query.Where(p => p.Email.Contains(txtEmailFilter.Text.Trim()));
}
if (!drpGender.SelectedValue.Equals("ALL"))
{
query = (IOrderedQueryable<MainDataMX.TblShadChanim>)query.Where(p => p.IsMale == (bool?)bool.Parse(drpGender.SelectedValue));
}
return query;
}
}
above code is not working.please reply back.
just use Count with Grouping, please check the following links:
Group and count items
linq with groupby and count
Hope to be in use
:)

Select two columns from the table via linq

I use the query below to get all columns(20 more) in Entity Framework Linq. Because of out of memory exception, I only want to get two of them. One is "FileName", the other one is "FilePath". How to modify my code?
var query = DBContext.Table1
.Where(c => c.FacilityID == facilityID && c.FilePath != null && c.TimeStationOffHook < oldDate)
.OrderBy(c => c.FilePath)
.Skip(1000)
.Take(1000)
.ToList();
foreach(var t in query)
{
Console.WriteLine(t.FilePath +"\\"+t.FileName);
}
var query = DBContext.Table1.Where(c => c.FacilityID == facilityID && c.FilePath != null && c.TimeStationOffHook < oldDate)
.OrderBy(c => c.FilePath)
.Skip(1000)
.Take(1000)
.Select(c => new { c.FilePath, c.FileName })
.ToList();
foreach(var t in query)
{
Console.WriteLine(t.FilePath +"\\"+t.FileName);
}
You need to use Select.
Just select out two of the columns:
DBContext.Table1.Select(c => new { c.FileName, c.FilePath });
How about something like
using (var entity = new MyModel(ConnectionString))
{
var query = (from myTable in entity.theTable
where myTable.FacilityID == facilityID &&
myTable.FilePath != null &&
myTable.TimeStationOffHook < oldDate
orderby myTable.FilePath
select new
{
myTable,FileName,
myTable.FilePath
}).Skip(1000).Take(1000).ToList();
//do what you want with the query result here
}

Categories