Search keyword using linq in asp.net with c#back end - c#

List<search> alllist = wsWSemloyee.GetAllProject(); //where search is model class contains properties..
string search_key = "%" + txtsearch.Text.Trim() + "%";
List<search> result = new List<search>();
foreach (search item in alllist)
{
var op = (
from a in alllist
where a.Sfirstname.Contains(search_key) || a.Slastname.Contains(search_key) || a.Smob.Contains(search_key) || a.Scity.Contains(search_key) || a.Sstate.Contains(search_key)
//where SqlMethods.Like(a.Sfirstname,search_key)||SqlMethods.Like(a.Slastname,search_key)||SqlMethods.Like(a.Scity,search_key)||SqlMethods.Like(a.Smob,search_key)||SqlMethods.Like(a.Sstate,search_key)
select a
);
// List<search> lst = op.ToList<search>();
if (op != null)
{
result.Add(item);
}
}
if (result.Count != 0)
{
dgv_searchreport.DataSource = result;
dgv_searchreport.DataBind();// data grid view
}
its not working...
giving all result present in alllist..
//where search is model class contains properties..

I'ts because you are comparing if result of your linq query is not null and then adding variable from foreach clause. When any single item from allproducts will match condition then op will be never null and then whole collection will be contained in result. What you want is probably following:
var result = (from a in alllist
where a.Sfirstname.Contains(search_key)
|| a.Slastname.Contains(search_key)
|| a.Smob.Contains(search_key)
|| a.Scity.Contains(search_key)
|| a.Sstate.Contains(search_key)
select a).ToList();
That will pick all items which match condition and enumerate them to list.

May this helps you..
string search_key = txtsearch.Text.Trim(); // instead "%" + txtsearch.Text.Trim() + "%";
List<search> result = new List<search>();
var op = (from a in alllist
where a.Sfirstname.Contains(search_key) || a.Slastname.Contains(search_key) || ......
select a);
if(op.Count() > 0)
result = op.ToList();

Related

LINQ - Match value, if not, return NULL element

I have a given date and I want to get the element on a table that is greater than the given date, but if it's not found, I want to return the element with the NULL date.
For example:
Table:
If the given date is, for example, 2019-10-20, I want to return the element with the ID 3.
If the given date is, for example, 2019-11-20, I want to return the element with the ID 4.
I've tried doing this:
var parameter = _db.Parameter
.OrderBy(x => x.EndDate)
.First(givenDate < x.EndDate) || x.EndDate == null);
But it's always returning the last element. What do I need to do?
You can try this:
var query = _db.Parameter
.OrderBy(x => x.EndDate)
.ToList();
var parameter = query.FirstOrDefault(x => givenDate < x.EndDate);
if ( parameter == null )
parameter = query.FirstOrDefault(x => x.EndDate == null);
if ( parameter == null )
...
else
...
We create an initial ordered query on the date, taking a list to evaluate the query.
Next we check if the first givenDate matching the desired result.
Else we try to get the first null row.
Then you can manage the final case.
To avoid parsing twice the query you can use that:
TheTypeOfParameter parameterFound = null;
TheTypeOfParameter parameterHavingDateNotNull = null;
TheTypeOfParameter parameterHavingDateNull = null;
bool foundDateNull = false;
bool foundDateNotNull = false;
foreach ( var item in query )
{
if ( !foundDateNull && item.EndDate == null )
{
parameterHavingDateNull = item;
foundDateNull = true;
}
else
if ( !foundDateNotNull && item.EndDate > givenDate )
foundDateNotNull = true;
if ( !foundDateNotNull )
parameterHavingDateNotNull = item;
if ( foundDateNotNull || foundDateNull )
break;
}
parameterFound = parameterHavingDateNotNull != null
? parameterHavingDateNotNull
: parameterHavingDateNull;
Because I can't test and debug, I hope this loop will work...
I would optimise the code by NOT using LINQ for this:
var parameter = _db.Parameter[0]; // you may need to handle that there's at least 1 item.
for (int i = 1; i < _db.Parameter.Count; i++)
{
var param = _db.Parameter[i];
if (param.EndDate > givenDate)
{ // param is good
if (parameter.EndDate == null || parameter.EndDate > param.EndDate)
parameter = param; // replace parameter with param
}
else if (parameter.EndDate != null && parameter.EndDate < givenDate)
{ // parameter precedes given date, replace it!
parameter = param;
}
}
This will iterate through your list just once, unlike the other solutions provided so far.
If you MUST use LINQ and want to iterate once, maybe you can use the below, which will return a dynamic though, so you need to convert it back to a Parameter. It works by replacing the NULL with DateTime.MaxValue so that when you do an OrderBy, the entries that were NULL would be ordered at the bottom.
var param = _db.Parameter
.Select(x => new
{
ID = x.ID,
EndDate = (x.EndDate.HasValue) ? x.EndDate : DateTime.MaxValue,
Value = x.Value
})
.OrderBy(x => x.EndDate)
.FirstOrDefault();
var parameter = new Parameter()
{
ID = param.ID,
EndDate = (param.EndDate == DateTime.MaxValue) ? null : param.EndDate,
Value = param.Value
};
As mentioned in the comments, NULL will be first after the ordering.
What if you try the following:
var parameter = _db.Parameter
.Where(x => (x.EndDate > givenDate) || (x.EndDate == null))
.OrderBy(x => x.EndDate)
.Last();
After selecting only earlier dates the latest is chosen. If only one element is in the list (the NULL element), this one gets chosen.

I cant seen to use ToList(); or take(6) items on this select statement

I cant seen to use ToList(); or take(6) items on this select statement.
I need to select only 6. this is what i have witch works but displays 1 only on the 6 iterations of the repeater.
public string GetImage(string pId)
{
Compras context = new Compras();
Product pr = context.Products.FirstOrDefault();
if (pr != null && pr.Picture != null && pr.Picture.Count() > 0)
{
return "data:image/jpg;base64," + Convert.ToBase64String((pr.Picture));
}
return "data:image/jpg;base64," + Convert.ToBase64String(File.ReadAllBytes(Server.MapPath("~/") + "white.jpg"));
}
I wish i could use as on this next:
var context = new Compras();
var prouctQ = from p in context.Products.Take(6) select new { p.ProductName, p.Picture }; //with projections
var Products = prouctQ.ToList();
if (Products.Count > 0)
Please make sure that you have "using System.Linq" at the top of the code file.

update linq to sql values with select new keyword

How to update linq to sql values with select new keyword with anonymous types because I am using var keyword with select new query I need in in this but it returns an error like this
Compiler Error Message: CS0200: Property or indexer 'AnonymousType#1.Code' cannot be assigned to -- it is read only
This is my code:
var ProjectView12 = (from x in db.Projects
select new
{
add = db.Locations.Where(y = > y.ID == x.RegionID).FirstOrDefault().Name,
Province = db.Locations.Where(y = > y.ID == x.ProvinceID).FirstOrDefault().Name,
District = db.Locations.Where(y = > y.ID == x.DistrictID).FirstOrDefault().Name,
Code = x.Code,
Name = x.Name,
ProjectIdentificationDate = db.Milestones.Where(y = > y.ProjectID == x.ID && y.StageID == 1 && y.ComponentID == 1 && y.ModuleID == 1).FirstOrDefault().Date.ToString(),
ProjectLat = Convert.ToDecimal(x.Lat),
ProjectLong = Convert.ToDecimal(x.Lon),
Remarks = db.Milestones.Where(y = > y.ProjectID == x.ID && y.StageID == 1 && y.ComponentID == 1 && y.ModuleID == 1).FirstOrDefault().Remarks.ToString(),
}).ToList();
foreach(var item in ProjectView12)
{
item.Code = txtSubProjectCode.Text;
item.Name = txtSubProjectName.Text;
item.ProjectLat = Convert.ToDecimal(txtLatitude.Text);
item.ProjectLong = Convert.ToDecimal(txtLongitude.Text);
item.ProjectIdentificationDate = txtDate.Text;
item.Remarks = txtRemarks.Text;
} // txtLocation.Text = item.Region + ">" + item.Province + ">" + item.District;
try
{
db.SubmitChanges();
}
catch (Exception ex)
{
throw ex;
}
Well, you're getting the compiler error because - as it says - the properties of anonymous types are read-only in C#.
More fundamentally, even if you could modify them, you'd have to expect LINQ to SQL to reverse whatever you put into your projection in order to update the original tables. That seems a fairly tall order to me - particularly for the Remarks property in this particular case.
Basically, in order to update the database, you need to make changes to the entities that are mapped from your tables. Make your query select the relevant entities, then you can project from those later on in client-side code, if necessary - so long as you've still got a reference to the entity to modify.

How do I add multiple optional parameters to linq query

I Have to check and add the optional parameter in function but its taking lengthy code to go through IF-Else statement, If I choose switch statement then Cannot convert 'var' variable to string error keep coming up, How do I check and add optional parameters to linq query please help. Here is my code. (I will provide both the one with If statement and other one with switch statement which is throwing error)
Code 1 If-else statement:
public static void loadGrid(ref GridView gvMain, string cID, string desig = "All", string importancy = "All", string status = "All")
{
int _cId = Convert.ToInt32(cID);
List<clsclass> list = new List<clsclass>();
var db = new MyEntities();
if (_cId == 0 && desig == "All" && importancy == "All" && status == "All")
{
var query = from table in db.Members select table;
list.Clear();
foreach (var item in query)
{
clsclass ctl = new clsclass();
ctl.Id = Convert.ToInt32(item.LID);
ctl.Name = item.FirstName + " " + item.LastName;
ctl.Gender = item.Gender;
ctl.Age = Convert.ToInt32(item.Age);
ctl.Mobile = item.Mobile;
ctl.Workphone = item.WorkPhone;
ctl.Designation = item.Designation;
ctl.Importancy = item.Importancy;
list.Add(ctl);
}
}
else if (_cId != 0 && desig == "All" && importancy == "All" && status == "All")
{
var query = from table in db.Members where table.CID == _cId select table;
list.Clear();
foreach (var item in query)
{
clsclass ctl = new clsclass();
ctl.Id = Convert.ToInt32(item.LID);
ctl.Name = item.FirstName + " " + item.LastName;
ctl.Gender = item.Gender;
ctl.Age = Convert.ToInt32(item.Age);
ctl.Mobile = item.Mobile;
ctl.Workphone = item.WorkPhone;
ctl.Designation = item.Designation;
ctl.Importancy = item.Importancy;
list.Add(ctl);
}
}
//AND SO ON I HAVE TO CHECK THE OPTIONAL PARAMETERS......
//else if()
//{
//}
}
And In below code If I try to use switch statement to bind query based condition its throwing error:
Code 2:Switch statement:
public static void LoadGrid(ref GridView gvMain, string cID, string desig = "All", string importancy = "All", string status = "All")
{
int _cId = Convert.ToInt32(cID);
List<clsclass> list = new List<clsclass>();
var db = new MyEntities();
var query;
switch (query)
{
case _cId == 0 && desig == "All" && importancy == "All" && satus == "All":
query = from b in db.ConstituencyLeaders select b;
case _cId != 0 && desig == "All" && importancy == "All" && satus == "All":
query = from b in db.ConstituencyLeaders where b.ConstituencyID == _cId select b;
}
foreach (var item in query)
{
clsclass cl = new clsclass();
cl.LeaderId = item.LID;
//...remaining members add
list.Add(cl);
}
gvMain.DataSource = list;
gvMain.DataBind();
}
So basically I got two questions How to shorten the codes to capture the optional parameters if switch statement is better option then how would I achieve var query from Case:
any help much appreciated.
What you can do is.
var query = db.Members.AsQuerryable();
if(_cid != "")
{
query = query.where(table => table.CID == _cId);
}
Then use that in your statement
var result = from table in query where table.CID == _cId select table;
or we also used to do or statements.
var query= from table in query where (table.CID == _cId || _cId = "") select table;
so if the value is empty it just goes through or if there is a value it checks.

c# linq to xml dynamic query

Right, bit of a strange question; I have been doing some linq to XML work recently (see my other recent posts here and here).
Basically, I want to be able to create a query that checks whether a textbox is null before it's value is included in the query, like so:
XDocument db = XDocument.Load(xmlPath);
var query = (from vals in db.Descendants("Customer")
where (if(textbox1.Text != "") {vals.Element("CustomerID") == Convert.ToInt32(textbox1.Text) } ||
if(textbox2.Text != "") {vals.Element("Name") == textbox2.Text})
select vals).ToList();
Just use the normal Boolean operators && and ||:
XDocument db = XDocument.Load(xmlPath);
var query = (from vals in db.Descendants("Customer")
where (textbox1.Text != "" &&
vals.Element("CustomerID") == Convert.ToInt32(textbox1.Text)) ||
(textbox2.Text != "" && vals.Element("Name") == textbox2.Text)
select vals).ToList();
That's just a direct translation of the original code - but I think you'll want a cast from vals.Element("CustomerID") to int, and you don't really want to convert textbox1.Text on every iteration, I'm sure. You also need to convert the "name" XElement to a string. How about this:
int? customerId = null;
if (textbox1.Text != "")
{
customerId = int.Parse(textbox1.Text);
}
XDocument db = XDocument.Load(xmlPath);
var query = (from vals in db.Descendants("Customer")
where (customerId != null &&
(int) vals.Element("CustomerID") == customerId) ||
(textbox2.Text != "" &&
(string) vals.Element("Name") == textbox2.Text)
select vals).ToList();
Alternatively, you could separate out the two parts of the query and "union" the results together. Or - preferably IMO - you could build the query more dynamically:
var query = db.Descendants("Customer");
if (textbox1.Text != null)
{
int customerId = int.Parse(textbox1.Text);
query = query.Where(x => (int) x.Element("CustomerID") == customerId);
}
if (textbox2.Text != null)
{
query = query.Where(x => (string) x.Element("Name") == textbox2.Text);
}
List<XElement> results = query.ToList();

Categories