Select rows without joining other tables regarding other tables - c#

I'm working in asp.net web forms 4.5 version.
I have trouble with linq.
I want to bring a table data.. (I don't want to join it.. as I would want it to be deleted and edited by the autodelete and autoedit button of gridview)
But I'm lost with linq.
I would like to do something like this..
public Iqueryable detailGrid_getData(){
string fromDStr = fromTBox.Text;
DateTime fromD = Convert.ToDateTime(fromDStr);
string toDStr = toTBox.Text;
DateTime toD = Convert.ToDateTime(toDStr);
var items = from s in db.salesOrderDetail_T where
db.salesOrder_T
.Select(so => so.poDate <= toD && so.poDate >=fromD)
.Contatins(s.soIdx) && s.stat == stat;
return items;
}
at which I got the idea from here : LINQ, select ID from Table where it does not match ID in another table
but for some reason, it doesn't work.
Will someone tell me why this is not working??
edit : It says a query body must end with a select clause or a group clause

The error message is quite clear here. Your query (items) does not end in a select clause, I think this is what you want:
var items = from s in db.salesOrderDetail_T where
db.salesOrder_T.Where(so => so.poDate <= toD && so.poDate >=fromD).Select(p=>p.Id).Contains(s.soIdx)
&& s.stat == stat
select s;

I would like to answer this because I figured it out totally different way.
Turns out that in LINQ, I can get around things in a lot of way.
This is the way I got through this..
Still not that expert in LINQ, but getting it.
var items = from so in db.salesOrderDetail_T
where so.poDate <= toD && so.poDate >= fromD
select so.idx;
soIdxList = items.toList();
items = items.Where(it => soIdxList.Contains((int) it.soIdx)
and then, use it.
Again, I'm not sure this is a good way to do things,
but it's easy and works.

Related

Linq to SQL to select rows whose DateTime field falls within any of a list of date ranges

I have a list of DateRange objects, which have StartDate and EndDate properties. I need to select all the rows from a table in my database which have a DateTime field that falls within any of those DateRanges. So I'd like to do something like this:
// Using an IQueryable<DateRange> called dateRanges
var tests = from test in dbContext.Tests
where dateRanges.Any(range => range.StartDate <= test.Date && range.EndDate >= test.Date)
select test
This gives me an error because DateRange is not a primitive type and so LINQ to SQL can't use it. Is there any other way to do what I'm trying to do here? Been googling and trying different things for a couple hours, I feel like I'm very close but can't quite get there. Thanks in advance.
Try to use Linq2Sql with dynamic query like
(p => value1.StartDate <= p.Date && value1.EndDate >= p.Date) || (p => value2.StartDate <= p.Date && value2.EndDate >= p.Date)
Example: Linq2SQL "or/and" operators (ANDed / ORed conditions)
The way I decided to do this in order to guarantee that no unnecessary data was being transferred was to create a stored procedure called GetTestsInDateRange on my database which takes in a start and end date and returns all of the tests that are in that range. Then in my code I'm looping through my list of DateRanges, calling the stored procedure once for each DateRange, and unioning the results together.
IEnumerable<Test> tests = new List<Test>();
foreach (DateRange range in selectedDateRanges)
{
tests = tests.Union(dbContext.GetTestsInDateRange(range.StartDate, range.EndDate));
}
Whether that's the ideal solution or not I don't know (probably depends on how many DateRanges were selected and therefore how many separate calls it's making to the database), but it's working well for my scenario.
Other that crafting your own SQL statement by concatenating the criteria for each range, one way to partially limit the results that you get back would be to use the min and max dates of the ranges, then filtering further in Linq-To-Objects:
var minStartDate = dateRanges.Min(r => r.StartDate);
var maxEndDate = dateRanges.Max(r => r.EndDate);
var tests = (from test in dbContext.Tests
where minStartDate <= test.Date && maxEndDate >= test.Date
select test)
.AsEnumerable() // change to Linq-To-Objects
.Where(test => dateRanges.Any(range => range.StartDate <= test.Date
&& range.EndDate >= test.Date));
This would work perfectly for one range, and would be only marginally worse unless your ranges had huge gaps in between them.

Combining LINQ queries in LINQ to CRM causes problems?

Something weird is going on.
If I do this:
var allAccountsQuery = from acc in baseQ
where
//high potential check - 1, 2, 3
(acc.mcpl_potencjal_klienta == 1 || acc.mcpl_potencjal_klienta == 2 || acc.mcpl_potencjal_klienta == 3) &&
//directors block check
((acc.mcpl_blokada_dyrektorska == true && acc.mcpl_blokada_do <= date) || acc.mcpl_blokada_dyrektorska == false || acc.mcpl_blokada_dyrektorska == null) &&
//sack assign date check
(acc.mcpl_dataprzypisaniazworka == null || acc.mcpl_dataprzypisaniazworka < date) &&
//owner change check
(acc.mcpl_datazmianywasciciela == null || acc.mcpl_datazmianywasciciela < date) &&
//creation date check
//TODO:For testing!
//(acc.mcpl_data_utworzenia_test < date)
(acc.createdon < date)
select acc;
var joinQuery = from acc in allAccountsQuery
join opp in ctx.opportunityopportunities on acc.accountid equals opp.customerid.Value
select new
{
Account = acc,
Opportunity = opp
};
Plugins.Common.XrmHelper.ClearCache("account");
var joinResult = joinQuery.ToList();
Then I'll get an unknown platform error when executing this query. I need to copy-paste the WHOLE where clause from allAccountsQuery to the joinQuery and use baseQ again, and then it works.
What's going on here? I thought you can safely join LINQ queries as long as you're not doing any unsupported operations.
PS. The STRANGEST part is that the pasted code WILL work with slightly different where conditions.
PPS. baseQ is just an even simpler where query, much like the allAccountsQuery.
Maybe is not the answer but as I can't leave a comment and no one has answer I think this could help.
Why you don't do the join in the first query? As from I know the LINQ CRM queries have problems joining tables when in the clause WHERE we have the OR Predicate, and not when we try to select from different tables, I think for you query should work. I have one post explaining what I learned.
Linq-to-CRM has a limited set of supported operations compared to other providers life EF or Linq-to-SQL.
You may have better success hydrating one or both of the two queries. Since your account query has a where clause try hydrating it:
var joinQuery = from acc in allAccountsQuery.ToList() // call ToList() to hydrate the query
join opp in ctx.opportunityopportunities
on acc.accountid equals opp.customerid.Value
select new
{
Account = acc,
Opportunity = opp
};
If you have a LARGE number of Opportunities you may want to try and filter that query based on the accounts returned from the first query before doing the Join.

Linq to DataSet filter one column for multi keywords

I have code like this:
var modele = from model in ds.Tables["modele"].AsEnumerable()
where model.Field<string>("KRAJ_PRODUKCJI") == krajText
&& model.Field<string>("FABRYKA") == fabrykaText
// && model.Field<string>("NAZWA") == itemId
orderby model.Field<string>("NAZWA")
select model;
In the commented out line I need to dynamically generate a where clause or check that the field NAZWA is equal to one of multiple keyword in itemId which is a list with a few keyword to check with || between.
Is it possible to do this?
Have you tried something like:
where itemId.Contains(model.Field<string>("NAZWA"))
I'm not sure if that's what you're looking for, but it might be.
#korchev's won't work because you want an "||".
Mam nadzieje ze to pomocne.
Might not work straight out-of-the-box, but I'm guessing you should look for your answer in this direction:
var keywords = itemId.split("||");
var model = from m in ds.Tables["modele"].AsQueryable();
model = model.Where(m => keywords.Contains(m.Field<string>("NAZWA"));

Linq, should I join those two queries together?

I have a Logins table which records when user is login, logout or loginFailed and its timestamp. Now I want to get the list of loginFailed after last login and the loginFailed happened within 24 hrs.
What I am doing now is get the last login timestamp first. then use second query to get the final list. do you think I should join those two queries together? Why not? Why yes? And how if yes?
var lastLoginTime = (from inRecord in db.Logins
where inRecord.Users.UserId == userId
&& inRecord.Action == "I"
orderby inRecord.Timestamp descending
select inRecord.Timestamp).Take(1);
if (lastLoginTime.Count() == 1)
{
DateTime lastInTime = (DateTime)lastLoginTime.First();
DateTime since = DateTime.Now.AddHours(-24);
String actionStr = "F";
var records = from record in db.Logins
where record.Users.UserId == userId
&& record.Timestamp >= since
&& record.Action == actionStr
&& record.Timestamp > lastInTime
orderby record.Timestamp
select record;
}
In the long run, I don't think it'd matter. No matter how you actually build the query in LINQ to SQL, the ultimate sequence of events on the DB server will be
get lastInTime
use lastInTime as part of records filter
Now... doing it as part of a single query will save on roundtrips of the actual date-time, so you can get some performance that way. But I would suggest that you only try to merge them if you absolutely need to because your performance profiling suggested that query was a bottleneck.
I don't think you should combine them because your current queries are quite readable. I think if they were combined it would be more difficult to understand the code.
I wouldn't merge, for reasons already stated by everyone else, but you can simplify the first query a bit: instead of
orderby inRecord.Timestamp descending
select inRecord.Timestamp).Take(1);
you can simply say:
select inRecord.Timestamp).Max();
It'll do the same thing, but it's a bit clearer than your way.
You can also use the IQueryable objects to compose more complex queries and still keep the code pretty easy to read. (I mixed the Extension syntax and query syntax just to show it can be done. You can just as easily swap this code around to separate it out as you would any other code in your solution.)
var usersRecords = db.Logins.Where(r => r.Users.UserId == userId);
var userLoginTimes = usersRecords.Where(r => r.Action == "I")
.Select(r => r.Timestamp);
var usersFunctions = usersRecords.Where(r => r.Action == "F");
var records = from record in usersFunctions
where userLoginTimes.Any()
let lastLoginTime = userLoginTimes.Max()
where record.Timestamp >= since
&& record.Timestamp > lastLoginTime
select record;

how do i get the min from a linq to dataset query

Hi i have a linq query below
var Free = (from row in
dt.AsEnumerable()
where row.Field("AppointmentType")
== "FreeTime"
select new{ row.Field("BookedDate")
row.Field("TravelTime")}).Min()
what i want to do is have a minimum on the travelTime field and im not sure on how to do it i have looked on google and also on the msdn site but i cant seem to make head or tail of it
does anyone have any ideas??
Many thanks
You could use an overload for Enumerable.Min():
var Free = (
from row in dt.AsEnumerable()
where row.Field("AppointmentType") == "FreeTime"
select new {
BookedDate = row.Field("BookedDate"),
TravelTime = row.Field("TravelTime")
}
).Min(x => x.TravelTime);
Actually, there is no need to look at the BookedDate and you should instead use
var Free = (
from row in dt.AsEnumerable()
where row.Field("AppointmentType") == "FreeTime"
select row.Field("TravelTime")
).Min();
I kept your original code with a few modifications to demonstrate the syntax for creating anonymous types.

Categories