My query is below. Can someone help me how to add dbquery inside my Linq statement? There is a comment "Add Where here". I'm struggling since yesterday. Idea is to form a LINQ statement and get the list at once. Thank you.
String dbwhere = "";
if (ddlName.SelectedItem.Value != "")
{
dbwhere = " && (User.Name == '" + ddlName.SelectedItem.Value.TrimEnd() + "')";
}
if (ddlHeightFrom.SelectedItem.Value != "")
{
dbwhere = dbwhere + " && (Physical.Height >= '" + ddlHeightFrom.SelectedItem.Value.TrimEnd() + "')";
}
if (ddlHeightTo.SelectedItem.Value != "")
{
dbwhere = dbwhere + " && (Physical.Height <= '" + ddlHeightTo.SelectedItem.Value.TrimEnd() + ")";
}
var usersquery = (
from physical in dbContext.Physicals
join user in dbContext.User on physical.UserID equals user.UserID
join photos in dbContext.Photo on User.UserID equals photos.UserID
where photos.PhotoNum == 1 && photos.Status == true
// ======= Add dbwhere here ============
select new
{
photos.PhotoURL,
photos.PhotoDescription,
user.State,
user.Country,
physical.EyesColor,
physical.HairColorInfo,
physical.HairTypeInfo,
physical.BodyHeight,
physical.BodyWeight,
}).ToList();
You can rewrite your query to avoid mixing linq with SQL (and make it safe from SQL injections)
var usersquery = (
from physical in dbContext.Physicals
join user in dbContext.User on physical.UserID equals user.UserID
join photos in dbContext.Photo on User.UserID equals photos.UserID
where photos.PhotoNum == 1 && photos.Status == true
select new
{
physical,
user,
photos,
}; // do not put ToList here!
Now you can add your special checks:
if (ddlName.SelectedItem.Value != "")
{
var userName = ddlName.SelectedItem.Value.TrimEnd();
usersquery = usersquery.Where(x => x.user.Name == userName);
}
if (ddlHeightFrom.SelectedItem.Value != "")
{
var height = int.Parse(ddlHeightFrom.SelectedItem.Value.TrimEnd());
usersquery = usersquery.Where(x => x.physical.Height >= height);
}
// and so on
Now you can materialize your data with ToList
var result = usersquery.Select(x => new
{
x.photos.PhotoURL,
x.photos.PhotoDescription,
x.user.State,
x.user.Country,
x.physical.EyesColor,
x.physical.HairColorInfo,
x.physical.HairTypeInfo,
x.physical.BodyHeight,
x.physical.BodyWeight
}).ToList();
NOTE: I've write it in notepad, so it may have errors. However I hope idea is clear
Related
I have two linq queries, in the second query i use the first query as a sub query. Basically the first query does a groupby to return distinct rows of ContactID to use in the second query, which then does a groupby on idnumber to check for duplicates.
private IQueryable<Contact> GetDistinctContact()
{
IQueryable<Contact> query = (from contact in context.Contacts
where contact.EDITED.Equals(0)
&& contact.NOTACTIVE.Equals(false)
&& contact.ID > 10001
join client in context.Clients on new { ClientID = contact.ID, EDITED = 0, DELETED = false }
equals new { ClientID = client.ContactID, EDITED = client.EDITED, DELETED = client.DELETED }
join member in context.Members on new { MemberID = client.ID, EDITED = 0, DELETED = false }
equals new { MemberID = member.ClientID, EDITED = member.EDITED, DELETED = member.DELETED }
select contact);
return query.GroupBy(x => x.ID).Select(grp => grp.FirstOrDefault());
}
IQueryable<ContactDetailsViewModelPart> query = (from contact in GetDistinctContact()
where contact.IdNumber != null
&& !contact.IdNumber.Trim().Equals("")
&& contact.EDITED.Equals(0)
&& contact.NOTACTIVE.Equals(false)
&& contact.ID > 10001
group contact
by new ContactDetailsViewModelPart
{
IDNumber = contact.IdNumber,
LastName = contact.LastName
}
into idNumberGroup
where idNumberGroup.Count() > 1
select new ContactDetailsViewModelPart
{
IDNumber = idNumberGroup.Key.IDNumber,
LastName = idNumberGroup.Key.LastName
});
return query.ToList();
This is the error i get. I am using Firebird database.
Dynamic SQL Error
SQL error code = -104
Token unknown - line 19, column 9
APPLY
EF generates SQL with a cross apply on sub query. I know this is not supported in later versions of Firebird. Any alternatives to this?
I think the first query could be eliminated (I guess contact.ID is a primary key), and use something like this:
var query =
from contact in context.Contacts
where contact.IdNumber != null
&& !contact.IdNumber.Trim().Equals("")
&& contact.EDITED.Equals(0)
&& contact.NOTACTIVE.Equals(false)
&& contact.ID > 10001
&& context.Clients.Any(client =>
client.ContactID == contact.ID && client.EDITED == contact.EDITED && client.DELETED == contact.EDITED
&& context.Members.Any(member =>
member.ClientID == client.ID && member.EDITED == client.EDITED && member.DELETED == client.DELETED
)
)
group contact
by new ContactDetailsViewModelPart
{
IDNumber = contact.IdNumber,
LastName = contact.LastName
}
into idNumberGroup
where idNumberGroup.Count() > 1
select idNumberGroup.Key;
return query.ToList();
Normally Any would be translated to SQL EXISTS subquery, which in turn most of the databases will treat as INNER JOIN. Unfortunatlely I don't know if Firebird does that, but it's worth trying.
I have a data entry form where user will input DateFrom and DateTo fields.
Select From Date: <input type="text" id="datepickerfrom" name="datepickerfrom"/>
Select To Date: <input type="text" id="datepickerto" name="datepickerto"/>
<asp:Button ID="btnGetData" runat="server" OnClick="BtnGetData_Click" Text="Get Error List" />
I want to build a Linq query that retrieves only top 100 records in case if no input provided.
If user provides DateFrom and does not provide DateTo, the user will select data which is greater than DateFrom up to DateTime.Now.
If user provides DateTo and does not provide DateFrom, the user will select data which is less then DateTo.
I have the following now:
public static List<ErrorLogData> GetLogErrorData(string appName, InputData data)
{
SqlConnection con;
List<ErrorLogData> errorLogData = null;
string query = "";
if (data.DateFrom == "" && data.DateTo == "")
{
query += "from ld in logData.errorLogs.Take(10000)";
}
if (data.DateFrom == "" && data.DateTo != "")
{
query += "from ld in logData.errorLogs where ld.errorTime <= " + data.DateTo;
}
if (data.DateFrom != "" && data.DateTo == "")
{
query += "from ld in logData.errorLogs where ld.errorTime >= " + data.DateFrom + " && <= " + DateTime.Now;
}
if (data.DateFrom != "" && data.DateTo != "")
{
query += "from ld in logData.errorLogs where ld.errorTime >= " + data.DateFrom + " && <= " + data.DateTo;
}
DateTime dateFrom = Convert.ToDateTime(data.DateFrom);
DateTime dateTo = Convert.ToDateTime(data.DateTo);
using (con = new SqlConnection(ConfigurationManager.AppSettings[conKey]))
using (WebEntities logData = new WebEntities())
{
logData.CommandTimeout = 300;
var errorLog = query +
select new ErrorLogData
{
ErrorID = ld.errorID,
ErrorTime = ld.errorTime,
UserName = ld.username,
ErrorType = ld.errorType,
Error = ld.error,
ControlNumber = ld.controlNumber
};
errorLogData = errorLog.ToList();
}
return errorLogData;
}
I'm not sure how to append query to "select new ErrorLogData..." statement to have the entire query.
What is the approach here?
You should just be able to use the IQueryable result of error log, and then perform lambda expressions for your if statements.
List<ErrorLogData> errorLogData = null;
DateTime dateFrom = Convert.ToDateTime(data.DateFrom);
DateTime dateTo = Convert.ToDateTime(data.DateTo);
//IQueryable errorLog
var errorLog = from ld in logData.errorLogs
select new ErrorLogData
{
ErrorID = ld.errorID,
ErrorTime = ld.errorTime,
UserName = ld.username,
ErrorType = ld.errorType,
Error = ld.error,
ControlNumber = ld.controlNumber
};
if (data.DateFrom == "" && data.DateTo == "")
{
errorLogData = errorLog.Take(10000);
}
if (data.DateFrom == "" && data.DateTo != "")
{
errorLogData = errorLog.where(x => x.ErrorTime <= dateTo).ToList();
//query += "from ld in logData.errorLogs where ld.errorTime <= " + data.DateTo;
}
//contine to implement If
return errorLogData;
Assuming that you are using some kind of LINQ data access technology, use something like the following:
private List<Entity> GetData(DateTime? dateFrom, DateTime? dateTo)
{
IQueryable<Entity> query = ...; //Here reference your table
if (dateFrom == null && dateTo == null)
{
query = query.Take(100);
}
else
{
DateTime dateToValue = dateTo ?? DateTime.Now;
query = query.Where(x => x.Date <= dateToValue);
if (dateFrom != null)
{
query = query.Where(x => x.Date >= dateFrom.Value);
}
}
return query.ToList(); //This will actually execute the query. Here you can expand your query to select specific columns before executing ToList
}
Following is the UI :
And this is code snippet i am using to fire dynamic where clause :
public void bind()
{
string filter = "";
if (!string.IsNullOrEmpty(txtPart.Text))
{
filter = filter + "masterinv.inv_item_id = " + txtPart.Text;
}
if (!string.IsNullOrEmpty(txtDescription.Text))
{
if (!string.IsNullOrEmpty(filter))
{
filter = filter + " || masterinv.description = " + txtDescription.Text;
}
else
{
filter = filter + "masterinv.description = " + txtDescription.Text;
}
}
if (!string.IsNullOrEmpty(txtVendor.Text))
{
if (!string.IsNullOrEmpty(filter))
{
filter = filter + " || vendor.vendor_name = " + txtVendor.Text;
}
else
{
filter = filter + "vendor.vendor_name = " + txtVendor.Text;
}
}
InventoryDataContext dc = new InventoryDataContext(InventoryDBContext.GetConnectionstring());
var searchResult = (from masterinv in dc.OMS_REF_Master_Inventories
join vendor in dc.OMS_REF_Vendors on masterinv.inv_item_id equals vendor.inv_item_id
Where(filter)
select new OMS_REF_Master_Inventory
{
inv_item_id = masterinv.inv_item_id,
description = masterinv.description,
unit_of_measure = masterinv.unit_of_measure,
lot_id = masterinv.lot_id,
serial_id = masterinv.serial_id,
mfg_id = masterinv.mfg_id,
mfg_item_id = masterinv.mfg_item_id,
item_status_current = masterinv.item_status_current,
cm_unit_cost = masterinv.cm_unit_cost,
sync_dte = masterinv.sync_dte
}).ToList();
searchResult;
}
In the above code filter created on the basis of combination of combo box and text field
selection.
Out of these one filter is :
masterinv.inv_item_id = 'A' || masterinv.description = 'F' || vendor.vendor_name = 'V'
it may vary depend upon the combobox value selection. All cases of Combo box present in BuildQueryFilter Method.
PROBLEM :
I am not able to fire where clause in this join. Where i am going wrong ?
I think you cannot use those % with linq queries.
Instead of % you can use Contains()/StartsWith()/EndsWith()
refer this for more info...
How to do SQL Like % in Linq?
How to do a LIKE query with linq?
Or
Use Sql Methods..
where SqlMethods.Like(c.CustomerName, "%/abc/%")
The code is listed below , is my code for multimode search in ado.net , i use now entity framework and i dont know how write this perfectly with less code
string query = '"SELECT id From user";
if(filter1 != "" || filter2 != "")
{
query += "where ";
}
if(filter1 != "")
{
query += "name='" + filter1 + "'";
if(filter2 != "")
query += " and "
}
if(filter2 != "")
query += "name" + filter2;
Try this:
var result = (from s in db.user
select s).AsQueryable();
if (filter1 != "")
{
result = result.Where(x=>x.name == filter1);
}
if (filter2 != "")
{
result = result.Where(x=>x.name == filter2);
}
var output = result.ToList();
Sample:
YourIQueryableResults.Where(x => filter1!="" && (x.Name == filter1))
or
if (filter1!="") { YourIQueryableResults = YourIQueryableResults.Where(x => x.Name == filter1)}
I have 3 tables:
Dealerships
------------
ID, Name, Website
Locations
------------
ID, DealershipID, Address, Ect.
Contacts
------------
ID, LocationID, Name, Ect.
So the relationship shows that we have dealerships who have multiple locations (Example: Weed Chevrolet of PA, Weed Chevrolet of NJ) and then each location has its own contacts (Example: Managers of PA location, Managers of NJ location). I need to join the 3 tables together. This is what I have:
var results = from d in entities.dealerships
join l in entities.locations on d.ID equals l.DealershipID
join c in entities.contacts on l.ID equals c.LocationID
select new
{
Name = d.Name,
Website = d.Website,
Address = l.Address + ", " + l.City + ", " + l.State + " " + l.Zip,
Contact = c.FirstName + " " + c.LastName,
WorkPhone = c.WorkPhone,
CellPhone = c.CellPhone,
HomePhone = c.HomePhone,
Email = c.Email,
AltEmail = c.AltEmail,
Sells = l.Sells
}
When I attempt to bind results to a BindingSource and then to a DataGridView I receive the following error:
Unable to cast the type 'System.Nullable`1' to type 'System.Object'.
LINQ to Entities only supports casting Entity Data Model primitive types.
What can it be? I am new to JOIN statements in LINQ so I am sure I am doing something wrong.
EDIT: There is data in the database so the results shouldn't be null, just to clarify
You were close but I discovered that you have to convert it from LINQ-To-Entities to LINQ-To-Objects. First I had to cast the entities using AsEnumerable() then use ToList(). This made it so I could use functions like ToString() and String.Format(). Thanks for leading me in the right direction. Here is the final code:
var query = from d in entities.dealerships
from l in entities.locations.Where(loc => loc.DealershipID == d.ID).DefaultIfEmpty()
from c in entities.contacts.Where(cont => cont.LocationID == l.ID).DefaultIfEmpty()
where d.Keywords.Contains(keywords) || l.Keywords.Contains(keywords) || l.Sells.Contains(keywords) || c.Keywords.Contains(keywords)
select new
{
Dealership = d,
Location = l,
Contact = c
};
var results = (from r in query.AsEnumerable()
select new
{
Name = r.Dealership.Name,
Website = r.Dealership.Website,
Contact = r.Contact.FirstName + " " + r.Contact.LastName,
Address = r.Location.Address + ", " + r.Location.City + ", " + r.Location.State + " " + r.Location.Zip,
WorkPhone = r.Contact.WorkPhone,
CellPhone = r.Contact.CellPhone,
Fax = r.Contact.Fax,
Email = r.Contact.Email,
AltEmail = r.Contact.AltEmail,
Sells = r.Location.Sells
}).ToList();
bindingSource.DataSource = results;
Since your results is IQueryable, EF will try to cast on the data store side and it won't work because cast only works with scalar types. You should call ToList() on the results like this:
var results = (from d in entities.dealerships
join l in entities.locations on d.ID equals l.DealershipID
join c in entities.contacts on l.ID equals c.LocationID
select new
{
Name = d.Name,
Website = d.Website,
Address = l.Address + ", " + l.City + ", " + l.State + " " + l.Zip,
Contact = c.FirstName + " " + c.LastName,
WorkPhone = c.WorkPhone,
CellPhone = c.CellPhone,
HomePhone = c.HomePhone,
Email = c.Email,
AltEmail = c.AltEmail,
Sells = l.Sells
}).ToList();
var EmplistDriver = (from a in data
join b in db.DesignationDetails on a.DesignationID equals b.DesignationDetailID into EmployeeBonus
from b in dataBonus.DefaultIfEmpty()
join x in db.EmployeeCommission on a.EmployeeDetailID equals x.EmployeeDetailID into EmployeeCommission
from x in dataComm.DefaultIfEmpty()
join c in db.EmployeeAdvance on a.EmployeeDetailID equals c.FKEAEmployeeID
join d in db.EmployeeAllowance on a.EmployeeAllowanceID equals d.EmployeeAllowanceID
join e in dataAtt on a.EmployeeDetailID equals e.EmployeeDetailID
join f in dataDri on a.EmployeeDetailID equals f.EmployeeDetailID
join h in db.ProjectAllocation on f.FKAllocationID equals h.PKAllocationID
join i in db.ProjectDetails on h.FKProjectDetailID equals i.ProjectDetailID
where a.IsActive == true && c.EAIsActive == true && d.IsActive == true && e.EAIsActive == true && h.IsActivity == true
select new
{
c.BalanceAmount,
c.BalanceDue,
d.FoodAllowance,
i.DriverBasicSalary,
d.OtherAllowance,
d.AccommodationAllowance,
e.EABasicWorktime,
BonusAmount = (b.BonusAmount == null ? 0 : b.BonusAmount),
CommissionAmount = (x.CommissionAmount == null ? 0 : x.CommissionAmount),
TotalOverTime,
TotalHr
}).FirstOrDefault();