LINQ: How can I shorten my code? - c#

I have done some LINQ, it works great but I'm not a fan of this type of coding, I would like to shorten it down, but not quite sure how to.
Does anyone know how I can shorten this section of code? I've heard of predicates before but not quite sure how to implement them?
List<Voucher> list = new List<Voucher>();
if (String.IsNullOrEmpty(Search.SearchText) && Search.Status == 0)
{
list = (from voucherslist in db.Vouchers
//where voucherslist.Status != (int)VoucherStatus.Removed
select voucherslist)
.Take(100)
.ToList();
}
if (!String.IsNullOrEmpty(Search.SearchText) && Search.Status ==0)
{
list = (from voucherslist in db.Vouchers
where voucherslist.Title.Contains(Search.SearchText)
select voucherslist).Take(100).ToList();
}
if (String.IsNullOrEmpty(Search.SearchText) && Search.Status > 0)
{
list = (from voucherslist in db.Vouchers
where voucherslist.Status == Search.Status
select voucherslist).Take(100).ToList();
}
if (!String.IsNullOrEmpty(Search.SearchText) && Search.Status > 0)
{
list = (from voucherslist in db.Vouchers
where voucherslist.Status == Search.Status
&& voucherslist.Title.Contains(Search.SearchText)
select voucherslist).Take(100).ToList();
}
// Convert
ret = VouchersConverter.Convert(list);
// Get Business Details
foreach (ENT_Voucher item in ret)
item.BusinessDetails = this._businessesBLL.GetBusinessDataByID(item.BusinessID);
// Refine and sort
ret = ret.Where(x=>x.BusinessDetails.Accept == true)
.OrderByDescending(x => x.Status.Equals(1))
.ThenByDescending(x => x.StartDate).ToList();

To remove the repetition, first set up your list.
list = (from voucherslist in db.Vouchers
//where voucherslist.Status != (int)VoucherStatus.Removed
select voucherslist);
Then add the title search if you need it:
if (!String.IsNullOrEmpty(Search.SearchText))
{
list = list.Where(x => x.Title.Contains(Search.SearchText));
}
And the status search:
if (Search.Status > 0)
{
list = list.Where(x => x.Status == Search.Status);
}
And finally, take your 100 and flatten it to a list.
list = list.Take(100).ToList();
The thing to bear in mind is that this will not actually construct and execute the SQL query until the .ToList() call, and the SQL that will be executed will contain all of the filtering you have concatenated together.

Your current logic looks a bit broken to me, but I suspect you want:
var query = db.Vouchers;
if (...)
{
query = query.Where(v => v.Title.Contains(Search.SearchText);
}
if (...)
{
query = query.Where(v => v.Status == Search.Status);
}
// etc
List<Voucher> list = query.Take(100).ToList();
Using multiple calls to Where will effectively apply an "AND" on all the filters.

Related

Check if parameter value is null or not inside query

In my query I am getting records based on RoleId and LocationId, some times the user may not pass location in that case I want to remove that filter and get information from all locations.
Currently I am doing this way
if(loc > 0)
{
var myResult = (from x in CSDB.Allocations
join s in CSDB.Managers
on x.ManagerId equals s.Id
Where x.RoleId == 2 && s.LocationId == loc
select new
{
x.name,
x.Date
}).ToList();
}
else
{
var myResult = (from x in CSDB.Allocations
join s in CSDB.Managers
on x.ManagerId equals s.Id
Where x.RoleId == 2
select new
{
x.name,
x.Date
}).ToList();
}
I am seeing if I can check if loc is null or not inside the query instead of using if else.
You can do something like this:
Where x.RoleId == 2 && (loc == null || s.LocationId == loc)
Also, you can do smth like this.
Where x.RoleId == 2 && (loc?.Equals(s.LocationId) ?? true)
If loc just int I would prefer to use a little bit changed #Salah Akbari answer:
Where x.RoleId == 2 && (loc == 0 || s.LocationId == loc)
Simply extract your managers and filter them if needed. That way you can as well easily apply more filters and code readability isn't hurt.
var managers = CSDB.Managers.AsQueryable();
if(loc > 0)
managers = managers.Where(man => man.LocationId == loc);
var myResult = from allocation in CSDB.Allocations
join manager in managers on allocation.ManagerId equals manager.Id
where allocation.RoleId == 2
select new
{
allocation.name,
allocation.Date
};

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
:)

Merge two Ordering Results into one result in linq with C#

I order two types of query. I want to show the result as one. if the first query and second query have count these both are merge and show the results of one. So i have created 3 list like jobs, jobs1, jobs2. I am getting values into jobs1 and jobs2. Then i have assigned using union into jobs3
Code
IQueryable<Job> jobs = _repository.GetJobs();
IQueryable<Job> jobs1 = _repository.GetJobs();
IQueryable<Job> jobs2 = _repository.GetJobs();
List<int> lstId = null;
List<int> lstUpdatedListId = null;
List<int> lstConId=null;
var order = _db.GetOrderDetails().Where(od => od.Masters.Id != null && od.OrderId == od.Master.OrderId && od.Master.Status == true && od.ValidityTill.Value >= currentdate).OrderByDescending(od => od.ValidityTill).Select(ord => ord.Master.Id.Value);
var order1 = _vasRepository.GetOrderDetails().Where(od => od.Masters.ConId != null && od.OrderId == od.Masters.OrderId && od.Masters.PaymentStatus == true && od.ValidityTill.Value >= currentdate).OrderByDescending(od => od.ValidityTill).Select(ord => ord.Masters.ConId.Value);
var updatedVacancyList = _repository.GetJobs().Where(c => c.UpdatedDate != null && updateFresh <= c.UpdatedDate).Select(c => c.Id);
if (order1 .Count() > 0)
{
lstConId = order1.ToList();
Func<IQueryable<Job>, IOrderedQueryable<Job>> orderingFunc = query =>
{
if (order1.Count() > 0)
return query.OrderByDescending(rslt => lstConId.Contains(rslt.Con.Id)).ThenByDescending(rslt=>rslt.CreatedDate);
else
return query.OrderByDescending(rslt => rslt.CreatedDate);
};
jobs1 = orderingFunc(jobs);
}
if (order.Count() > 0)
{
lstId = order.ToList();
lstUpdatedJobsListId = updatedVacancyList.ToList();
Func<IQueryable<Job>, IOrderedQueryable<Job>> orderingFunc = query =>
{
if (order.Count() > 0)
return query.OrderByDescending(rslt => lstId.Contains(rslt.Id)).ThenByDescending(rslt => lstUpdatedJobsListId.Contains(rslt.Id)).ThenByDescending(rslt=>rslt.CreatedDate);
if (updatedVacancyList.Count() > 0)
return query.OrderByDescending(rslt => lstUpdatedJobsListId.Contains(rslt.Id)).ThenByDescending(rslt => rslt.UpdatedDate);
else
return query.OrderByDescending(rslt => rslt.CreatedDate);
};
jobs2 = orderingFunc(jobs);
}
jobs = jobs1.Union(jobs2);
and i am getting an error while run the application as follows,
The text data type cannot be selected as DISTINCT because it is not comparable.
I need help to rectify this issue. I want to order in descending also.
One of your columns in Database is "Text" type. Convert it to varchar(MAX)

Dynamically Building LINQ-To-Entities Where Clause

How can I build the where clause dynamically, Some time the OwnerID will be zero only itemID and LocationIDwill be provided as the search criteria, in that case the LINQ should be
(from s in repository.ItemOwners.Include("OwnerDetails")
where s.ItemId == searchCriteria.ItemID &&
s.OwnerDetails.LocationId == searchCriteria.LocationID
select new { s.OwnerDetails.OwnerName, s.OwnerDetails.MobNumber }).ToList();
Some time the OwnerID and ItemId will be zero then only the LocationID will be provided as the search criteria, in that case the LINQ should be
(from s in repository.ItemOwners.Include("OwnerDetails")
where s.OwnerDetails.LocationId == searchCriteria.LocationID
select new { s.OwnerDetails.OwnerName, s.OwnerDetails.MobNumber }).ToList();
Some time the whole OwnerID, ItemID and LocationID will be provided as the search criteria, then the LINQ will be like this
(from s in repository.ItemOwners.Include("OwnerDetails")
where s.OwnerId == searchCriteria.OwnerID &&
s.ItemId == searchCriteria.ItemID &&
s.OwnerDetails.LocationId == searchCriteria.LocationID
select new { s.OwnerDetails.OwnerName, s.OwnerDetails.MobNumber }).ToList();
Here only the where clause is changing, Please help me to solve. How I can I build the where clause dynamically (Please note, here I am having a navigation property which is OwnerDetails.LocationId).
You can easily do it by using method-based query. You can add the conditions one at a time and call Select and ToList at the end:
// Where(x => true) might not be necessary, you can try skipping it.
var query = repository.ItemOwners.Include("OwnerDetails").Where(x => true);
if (searchCriteria.OwnerID != null)
query = query.Where(s => s.OwnerID == searchCriteria.OwnerID);
if (searchCriteria.ItemID != null)
query = query.Where(s => s.ItemID == searchCriteria.ItemID);
if (searchCriteria.OwnerID != null)
query = query.Where(s => s..OwnerDetails.LocationId == searchCriteria.LocationID);
var results = query.Select(s => new { s.OwnerDetails.OwnerName, s.OwnerDetails.MobNumber }).ToList();
Simplest is just check the zero condition in the Where clause:
(from s in repository.ItemOwners.Include("OwnerDetails")
where (searchCriteria.OwnerID == 0 || s.OwnerId == searchCriteria.OwnerID) &&
(searchCriteria.ItemID == 0 || s.ItemId == searchCriteria.ItemID) &&
s.OwnerDetails.LocationId == searchCriteria.LocationID
select new { s.OwnerDetails.OwnerName, s.OwnerDetails.MobNumber }).ToList();

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