Searching on multiple strings - c#

I am having some issues with doing a search. I am trying to find a customer on either Name+Lastname, reference or CompanyName. I managed to get it working, however the the ordering is not 100%.
Here is my original object
var q = from row in DataAccess.metadata.db_Customer
where row.accountID == accountID
&& row.isActive
orderby row.Name
select new bl_customerNames
{
customerID = row.customerID,
CustomerName = row.Name + " " + row.LastName,
Company = row.Company,
Reference = row.reference,
Email = row.Email,
CurrencyCode = row.CurrencyCode,
isSuspended = row.isSuspended
};
Then I did the following filter.
if (!string.IsNullOrEmpty(search))
{
q = q.Where(x => (x.CustomerName.Contains(search) || x.Reference.Contains(search) || x.Company.Contains(search)));
}
Although this does a fair job the list does not really make logical sense as its does not favor starts with above Contains.
I then came up with a ranking solution where I would rank Starts with higher than Contains.
Here is my code for that:
var q = from row in DataAccess.metadata.db_Customer
where row.accountID == accountID
&& row.isActive
orderby row.Name
select new bl_customerNames
{
customerID = row.customerID,
CustomerName = row.Name + " " + row.LastName,
Company = row.Company,
Reference = row.reference,
Email = row.Email,
CurrencyCode = row.CurrencyCode,
isSuspended = row.isSuspended,
Rank = ((row.Name + " " + row.LastName).StartsWith(search) || row.reference.StartsWith(search) || row.Company.StartsWith(search)) ? 1 : ((row.Name + " " + row.LastName).Contains(search) || row.reference.Contains(search) || row.Company.Contains(search)) ? 2 : 0
};
I would then filter like this:
q = q.Where(r=>r.Rank > 0).OrderBy(r => r.Rank);
However if I search on reference it does not return anything.
So My question is will my current method work also why does nothing return if I search on reference or Company Name? What would the correct way of doing a StartsWith then Contains and still keeping some kind of alphabetical ordering after StartsWith List.
Please keep in mind I am still a junior developer and any help would be appreciated.

I went back to the basics and this is what I came up with.
//Get customers that starts with
var qSW = from row in DataAccess.metadata.db_Customer
where row.accountID == accountID
&& row.isActive
where (row.Name + " " + row.LastName).StartsWith(search)
|| row.Company.StartsWith(search)
|| row.reference.StartsWith(search)
select new bl_customerNames
{
customerID = row.customerID,
CustomerName = row.Name + " " + row.LastName,
Company = row.Company,
Reference = row.reference,
Email = row.Email,
CurrencyCode = row.CurrencyCode,
isSuspended = row.isSuspended
};
//Order
qSW = qSW.OrderBy(r => r.CustomerName).ThenBy(r => r.Company).ThenBy(r => r.Reference);
//Get customers that contains
var qC = from row in DataAccess.metadata.db_Customer
where row.accountID == accountID
&& row.isActive
where (row.Name + " " + row.LastName).Contains(search)
|| row.Company.Contains(search)
|| row.reference.Contains(search)
select new bl_customerNames
{
customerID = row.customerID,
CustomerName = row.Name + " " + row.LastName,
Company = row.Company,
Reference = row.reference,
Email = row.Email,
CurrencyCode = row.CurrencyCode,
isSuspended = row.isSuspended
};
//If search is less then 3 chars limit to 10 to help with performance
if(search.Count() > 2)
qC = qC.OrderBy(r => r.CustomerName).ThenBy(r => r.Company).ThenBy(r => r.Reference);
else
qC = qC.OrderBy(r => r.CustomerName).ThenBy(r => r.Company).ThenBy(r => r.Reference).Take(10);
//Concat list leaving out duplicates
var SList = qSW.Concat(qC);
// Return List
return SList.ToList();
It seems to be doing the job and performance seems very good.

Related

When executing the linq query its throwing the casting error system.int32

var Appointment = (from app in _context.Appointments
join pt in _context.Patients on app.PatientID equals pt.ID into
patients
from pt in patients.DefaultIfEmpty()
join doc in _context.Doctors on app.DoctorID equals doc.ID into
doctors
from doc in doctors.DefaultIfEmpty()
//join offloc in _context.OfficeLocations on app.DoctorID
equals offloc.DoctorID into officlocation
//from offloc in officlocation.DefaultIfEmpty()
join docavail in _context.DoctorsAvailabilities on
app.AvailabilityID equals docavail.ID into availability
from docavail in availability.DefaultIfEmpty()
where ((app.CreatedByReferral == ReferralSpecialistID ||
app.CompanyID == CompanyID || app.UserGroupID == CompanyID) &&
app.OtherPatientID == null && pt.Status == StatusConstant.Active
&& app.Status != AppointmentRescheduledID &&
app.IsCloseAppointment != true)
select new AppointmentDataTableResult
{
appointmentID = app.ID,
PatientID = pt.ID,
patientname = (pt.NamePrefix ?? "") + " " + pt.FirstName + " " + pt.LastName + " " + (pt.NameSuffix ?? ""),
ParentPatientID = 0,
dateofbirth = pt.DateOfBirth,
patientType = _context.CategoryDetails.Where(x => x.ItemID == app.PatientTypeID).Select(x => x.MasterData).FirstOrDefault(),
phone = pt.Phone,
Date = docavail.Date,
Time = docavail.Time,
statustext = _context.CategoryDetails.Where(x => x.ItemID == app.Status).Select(x => x.MasterData).FirstOrDefault(),
doctorname = (doc.NamePrefix ?? "") + " " + doc.FirstName + " " + doc.LastName + " " + (doc.NameSuffix ?? ""),
DoctorID = doc.ID,
checkin = app.CheckIn,
checkout = app.CheckOut,
checkintime = app.CheckInTime,
checkouttime = app.CheckOutTime,
withoutslot = app.WithoutSlot,
locatioid = app.LocationID ?? 0,
AppointmentSource = app.AppointmentSource ?? 0,
Status = app.Status ?? 0,
IsPastAppointment = app.IsPastAppointment,
casestatusID = app.CaseStatusID ?? 0,
caseTypeID = app.CaseTypeID ?? 0,
ReferralAttorneyID = app.ReferralAttorneyID ?? 0,
ReferralProviderID = app.ReferralProviderID ?? 0,
patientTypeID = app.PatientTypeID ?? 0,
InsuranceID = app.InsuranceID ?? 0,
PendingAppointmentDate = app.PreferredAppointmentDateTime,
// AppointmentDate = docavail.Date.Value.Month + "/" + docavail.Date.Value.Day + "/" + docavail.Date.Value.Year + " " + docavail.Time.Value.Hours + ":" + docavail.Time.Value.Minutes,
ReportCount = _context.DoctorReportStatus.Where(x => x.StatusID == StatusConstant.Active && x.AppointmentID == app.ID).Count(),
RerecordUploadedYN = app.RerecordUploadedYN,
IsAppointmentPending = app.IsAppointmentPending,
IsPendingBillingRecoardYN = app.IsPendingBillingRecoardYN,
strDate = docavail.Date.Value.Month + "/" + docavail.Date.Value.Day + "/" + docavail.Date.Value.Year,
DateChekin = default(DateTime),
totaldays = 0
});
i also face same problem many time this problem occurs when you put Tolist method because before putting the Tolist() method the output generated by the query is of type
IQuerable
but this not the solution of your problem
the problem is that May be
1 you are assigning a Nullable integer type variable to non nullable integer type value or 2 comparing the Nullable integer value to Non Nullable value in Join or vice Versa
chances of second case is greater because when assigning ,c# compiler gives error
check your types of compared variable and let me give some follow ups.

how to convert type 'System.Collections.Generic.IEnumerable<AnonymousType#1>' to 'System.Collections.Generic.IEnumerable<>'.

I need to convert the following linq to a List directly,if I convert it to list I still get the error I explained on the subject,its said I need to convert it to list,but still the error is there,how can I convert it to list of string?without using additional conversion like foreach,...
List<string> eventResult= (from c in DB.Events
where (c.m_turbine_id == turbineid.turbineID) && (c.m_time_stamp >= frmDate && c.m_time_stamp <= toDate)
select new EventLogPartialViewModel
{
Timestamp = c.m_time_stamp,
Description = c.m_event_log_description,
WindSpeed = c.m_wind_speed,
RPM = c.m_rpm,
Power = c.m_power
}).ToList().Select(x => new
{
Timestamp = x.Timestamp.ToString("dd/MM/yyyy H:mm:ss"),
Description = x.Description,
WindSpeed = x.WindSpeed,
RPM = x.RPM,
Power = x.Power
}).ToList().OrderByDescending(m => m.Timestamp);
the first part of the above linq,i get the data and convert to list because I need to change my time stamp format,any help will be appreciated .
As you need to create list of comma separated values with header,
//Add headers as first item
List<string> eventResult = new List<string>(){"Timestamp,Description,WindSpeed,RPM,Power"};
//Add records
eventResult.AddRange(from c in DB.Events
where (c.m_turbine_id == turbineid.turbineID) && (c.m_time_stamp >= frmDate && c.m_time_stamp <= toDate)
select new EventLogPartialViewModel
{
Timestamp = c.m_time_stamp,
Description = c.m_event_log_description,
WindSpeed = c.m_wind_speed,
RPM = c.m_rpm,
Power = c.m_power
}).ToList().Select(x =>
x.Timestamp.ToString("dd/MM/yyyy H:mm:ss")) + "," +
x.Description + "," +
x.WindSpeed + "," +
x.RPM + "," +
x.Power
.ToList());
In the Linq query, you are selecting anonymous complex type so you can't assign it a List<string>. You should use var to keep reference of anonymous type.
var eventResult= (from c in DB.Events
where (c.m_turbine_id == turbineid.turbineID) && (c.m_time_stamp >= frmDate && c.m_time_stamp <= toDate)
select new EventLogPartialViewModel
{
Timestamp = c.m_time_stamp,
Description = c.m_event_log_description,
WindSpeed = c.m_wind_speed,
RPM = c.m_rpm,
Power = c.m_power
}).ToList().Select(x => new
{
Timestamp = x.Timestamp.ToString("dd/MM/yyyy H:mm:ss"),
Description = x.Description,
WindSpeed = x.WindSpeed,
RPM = x.RPM,
Power = x.Power
}).OrderByDescending(m => m.Timestamp).ToList();
Also, the ideal way is creating a class for complex type to handle reference instead of using anonymous type.

How to speed up the following Linq Query for Stock

I am write Programming in ASP.NET MVC with SQL Database. I want to get transfer list from database with between Date Range. Also the foreign key relationship with tables like product,Brand,sub-brand.
Here i wrote the code for getting list but it take time to load.The Database have 3000 records per month. how to optimize the code?
var stockTransferDetails = db.StockTransferDetails.Where(s => s.BusinessUnitId == BusinessUnitId && (!string.IsNullOrEmpty(from) ? s.StockTransfer.TransferDate >= FromDate : true) && (!string.IsNullOrEmpty(to) ? s.StockTransfer.TransferDate <= ToDate : true)).ToList();
var stocksummary = from STD in stockTransferDetails.GroupBy(f => f.ProductId).ToList()
select new
{
BrandName = STD.FirstOrDefault().Product.Brand.BrandName + STD.Where(m => !m.Product.SubBrand.BrandName.Equals("DEF")).Select(s => " - " + s.Product.SubBrand.BrandName).FirstOrDefault(),
ProductName = STD.FirstOrDefault().Product.ProductName,
Packsize = STD.FirstOrDefault().Product.Packsize + " " + STD.FirstOrDefault().Product.UOM.PickListValue,
// TotalQty = (double?)STD.Sum(s => s.ReceievedQty)
Cost = STD.FirstOrDefault().Product.Cost,
TotalCost = (STD.Sum(s => s.ReceievedQty) * STD.FirstOrDefault().Product.Cost)
};
OutletSTIn.Value = stocksummary.ToList();

Orderby not working

I am sorting on multiple criteria using dynamic sorting, here's my code:
public ActionResult WebGrid(int page = 1, int rowsPerPage = 10, string sortCol = "OrderID", string sortDir = "ASC", string sortSecCol = "OrderID", string sortSecDir = "ASC")
{
List<Orders> res;
using (var nwd = new NorthwindEntities())
{
var _res = nwd.Orders
.AsQueryable()
.OrderBy(sortCol + " " + sortDir, sortSecCol + " " + sortSecDir)
.Skip((page - 1) * rowsPerPage)
.Take(rowsPerPage)
.Select(o => new Orders
{
What I am trying to do in here is I want the column OrderID be the secondary sort whenever it is not a primary sort, but it didn't work when I actually selected other column as a primary sort.
In order words, when other column is select as primary sort in descending order, OrderID should also be in descending order, I am not sure what did I missed in my code.
The OrderBy method I used is come from here (MSDN).
The method you are using has the following signature:
public static IQueryable<T> OrderBy<T>(
this IQueryable<T> source,
string ordering,
params object[] values
)
so the sortSecCol + " " + sortSecDir goes to values argument, while the whole ordering is supposed to be provided as comma separated list in the ordering argument.
You can use something like this instead:
var ordering = sortCol + " " + sortDir;
if (sortSecCol != sortCol)
ordering += ", " + sortSecCol + " " + sortSecDir;
...
.OrderBy(ordering)
...
try this:
if (sortCol == "OrderID" && sortDir == "ASC")
{
_res = l.OrderBy(x => x.OrderId).ThenBy(x => x.AnotherField);
}
if (sortCol == "OrderID" && sortDir == "DESC")
{
_res = l.OrderByDescending(x => x.OrderId).ThenByDescending(x => x.AnotherField);
}
if (sortCol == "AnotherField" && sortDir == "ASC")
{
_res = l.OrderBy(x => x.AnotherField).ThenBy(x => x.OrderId);
}
if (sortCol == "AnotherField" && sortDir == "DESC")
{
_res = l.OrderByDescending(x => x.AnotherField).ThenByDescending(x => x.OrderId);
}
_res.Skip((page - 1) * rowsPerPage)
.Take(rowsPerPage)
.Select(o => new Orders
{

getting the MAX() value using LINQ [duplicate]

This question already has answers here:
C# Using LINQ to select max ID of row
(6 answers)
Closed 8 years ago.
I'm trying to select the max value of BreadCrumbID from the table tbBreadCrumb when I return multiple rows. Right now I join the tabel tbBreadCrumb to the table tbProjects. If there are multiple entries in tbBreadCrumb I return the multiple entries. But I only want to select the row in tbBreadCrumb that has the highest BreadCrumbID.
Here's my code:
using (dbPSREntities5 myEntities = new dbPSREntities5())
{
var allDepartments = (from tbProject in myEntities.tbProjects
from tbBreadCrumb in myEntities.tbBreadCrumbs.Where(x => x.ProjectID == tbProject.ProjectID) <--- I want to put some sort of Max() function here where it will only slect the row with the max BreadCrumID in the table tbBreadCrumb
from refBreadCrumb in myEntities.refBreadCrumbs.Where(x => x.refBreadCrumbID == tbBreadCrumb.StatusID)
// select new anon type
select new
{
ProjectID = tbProject.ProjectID,
Status = refBreadCrumb.BreadCrumbValue,
DateSubmitted = tbBreadCrumb.CreateDateTime,
refDepartmentID = tbProject.refDepartmentID,
ProjectContactFullName = tbProject.ProjectContactFirstName + " " + tbProject.ProjectContactLastName,
ProjectWorkType = tbProject.ProjectWorkType,
});
projectsListView.DataSource = allDepartments;
projectsListView.DataBind();
}
You can try this,first get the Maximum BreadCrumbID Id.Then use it with where in the second query :
var breadId = myEntities.tbBreadCrumbs.Max(x => x.BreadCrumbID);
var allDepartments = (from tbProject in myEntities.tbProjects
from tbBreadCrumb in myEntities.tbBreadCrumbs.Where(x => x.ProjectID == tbProject.ProjectID && x.BreadCrumbID == breadId)
from refBreadCrumb in myEntities.refBreadCrumbs.Where(x => x.refBreadCrumbID == tbBreadCrumb.StatusID)
// select new anon type
select new
{
ProjectID = tbProject.ProjectID,
Status = refBreadCrumb.BreadCrumbValue,
DateSubmitted = tbBreadCrumb.CreateDateTime,
refDepartmentID = tbProject.refDepartmentID,
ProjectContactFullName = tbProject.ProjectContactFirstName + " " + tbProject.ProjectContactLastName,
ProjectWorkType = tbProject.ProjectWorkType,
});
Update:
var allDepartments = (from tbProject in myEntities.tbProjects
from tbBreadCrumb in myEntities.tbBreadCrumbs.Where(x => x.ProjectID == tbProject.ProjectID && x.BreadCrumbID == myEntities.tbBreadCrumbs.Where(y => y.ProjectID == tbProject.ProjectID).Max(y => y.BreadCrumbID))
from refBreadCrumb in myEntities.refBreadCrumbs.Where(x => x.refBreadCrumbID == tbBreadCrumb.StatusID)
// select new anon type
select new
{
ProjectID = tbProject.ProjectID,
Status = refBreadCrumb.BreadCrumbValue,
DateSubmitted = tbBreadCrumb.CreateDateTime,
refDepartmentID = tbProject.refDepartmentID,
ProjectContactFullName = tbProject.ProjectContactFirstName + " " + tbProject.ProjectContactLastName,
ProjectWorkType = tbProject.ProjectWorkType,
});

Categories