Of course I made some research and tried something but can't make it.
I have this code so far:
var workLogs = (from wl in _db.WorkLogs
where (wl.Users_UserId == userId && wl.Works_WorkId == workId && wl.Date > beginDate && wl.Date < endDate)
select new
{
wl.Users_UserId,
wl.Works_WorkId,
wl.Time,
wl.Date
})
.AsEnumerable()
.Select(wl => new
{
userName = GetUserNameFromId(wl.Users_UserId),
workName = GetWorkNameFromId(wl.Works_WorkId),
wl.Time,
wl.Date
});
As you can see I tried enumeration but when I run the application, workLogs comes empty. And when I inspect it with a breakpoint, I see "Enumeration yielded no results."
What I trying to make is return work and user name in workLogs. And I wrote two method to do this. I just cant call them in my Linq query.
Without my methods, it works good as you can see it: http://i.imgur.com/ALb5f0K.png
And my methods also works good outside of query.
I hope I made myself clear.
If there are no results then it means your underlying source doesn't have data, or your where clause is filtering out more than you think it should be. There is no problem that you could have with your select statement(s) that would cause a sequence that would normally return results to instead return no results. At most you could cause it to throw an exception.
There is no reason why the following code should not work. You do not need other code to make this work.
If this return no results, it just means that the where clause is filtering everything.
Make a manual foreach with a if statement to debug this and you will see that there is no problem with your LINQ request.
var workLogs = from wl in _db.WorkLogs
where (wl.Users_UserId == userId && wl.Works_WorkId == workId && wl.Date > beginDate && wl.Date < endDate)
select new
{
GetUserNameFromId(wl.Users_UserId),
GetWorkNameFromId(wl.Works_WorkId),
wl.Time,
wl.Date
}
Try replacing .AsEnumerable() with .ToArray().
Related
I'm currently trying to achieve the following :
I have an IQueryable (UserDataDateRange) that has "from" and "to" DateTime-Values and another bigger IQueryable (UserData) with a DateTime-value and basically I want to exclude every data from userdata that Datetime-value is between the "from" and "to" comparing it to every UserDataDateRange-Entry.
Also every DateTime is nullable and I just want to ignore those.
Here is what I have tried :
private IQueryable<Userdata> ExcludeIfInDaterange(IQueryable<Userdata> query)
{
var dateRangeQuery = DBContext.UserDateDateRange.Where(x => x.From.HasValue && x.To.HasValue);
query = query.Where(l => !l.UserDate.HasValue);
foreach (var q in dateRangeQuery)
{
query = query.Where(l => l.UserDate.Value <= q.From.Value && l.UserDate.Value >= q.To.Value);
}
return query;
}
From my understanding this should work? Also I have tried avoid using something like "toArray" because from my understanding an IQueryable is basically the SQL that im manipulating and something toArray gives me the actual data.
However I really don't know what I'm doing wrong, theres no real exception, im just getting the following error :
Could not get function from a frame. The code is not available. The
error code is CORDBG_E_CODE_NOT_AVAILABLE, or0x80131309.
My function seems to break the query but i cant figure out why. I cant even use "Count()", it gives me the same error.
Anyone got an idea?
l.UserDate.Value <= q.From.Value && l.UserDate.Value >= q.To.Value
How can a date be both earlier than the From date and later than the To date at the same time? Unless you have some very odd data in your UserDateDateRange table, that filter will exclude all records.
You're also combining two mutually-exclusive filters with an AND operator, which is another way to exclude all records:
!l.UserDate.HasValue : UserDate is NULL
l.UserDate.Value <= ... : Can't possibly be satisfied, since UserDate is NULL
And there's no need to use .Value when comparing nullable properties with < / <= / > / >=.
Try something like:
private IQueryable<Userdata> ExcludeIfInDaterange(IQueryable<Userdata> query)
{
var dateRangeQuery = DBContext.UserDateDateRange.Where(x => x.From.HasValue && x.To.HasValue);
return query.Where(l => !l.UserDate.HasValue || !dateRangeQuery.Any(q => q.From <= l.UserDate && l.UserDate <= q.To));
}
I'm trying to create an LINQ Query with 4 arguments in the Where clause. It's a Windows 8 App project and I'm using an SQLite Database. (SQLite implementation )
Here's the code snippet:
public List<FinancialListBoxExpenseItem> retrieveExpenseItems(int month, int year, bool isPaid, StaticResources.FrequencyEnum frequencyEnum)
{
List<FinancialListBoxExpenseItem> tmpList = null;
connection.RunInTransaction(() =>
{
var items = from s in connection.Table<FinancialListBoxExpenseItem>()
where (s.expenseDateNextPayment.Month == month)
&& (s.expenseDateNextPayment.Year == year)
&& (s.expensePaidForCurrentPeriod == isPaid)
&& (s.expenseFrequencyTypeEnum == frequencyEnum)
select s;
tmpList = items.ToList<FinancialListBoxExpenseItem>();
});
return tmpList;
}
It throws a NotSupportedAction: Member access failed to compile expression Exception
I have no idea what does this mean and how i'm supposed to fix it.
Edit: it works without the where clause therefore the error must be related to this where clause part of the code
Probably .Month is not supported by your LINQ provider. You'll have to work around that, possibly by creating specialized columns for the month and the year.
This is how i solved the problem:
public List<FinancialListBoxExpenseItem> retrieveExpenseItems(int month, int year, bool isPaid, StaticResources.FrequencyEnum frequencyEnum)
{
List<FinancialListBoxExpenseItem> tmpList = new List<FinancialListBoxExpenseItem>();
connection.RunInTransaction(() =>
{
var items = from s in connection.Table<FinancialListBoxExpenseItem>()
let convertedDate = (DateTime)s.expenseDateNextPayment
where (convertedDate.Month == month)
&& (convertedDate.Year == year)
&& (s.expensePaidForCurrentPeriod == isPaid)
&& (s.expenseFrequencyTypeEnum == frequencyEnum)
select s;
tmpList = items.ToList();
});
return tmpList;
}
In my App I was getting a NotSupportedException when running a LINQ query, and the details of the exception showed
Member access failed to compile expression
As this thread let me know, the issued seemed to be caused by a DateTime variable that was being referenced in the query. Outside of finding a StackOverflow thread like this one to point you in the right direction, I'm not sure how anyone is supposed to figure that out on their own, but for me, changing the way I was writing the query fixed the problem.
This syntax was throwing the "NotSupportedException":*
IEnumerable<Foo> foos = connection.Table<Foo>().Where(foo => foo.Timestamp.Year == year);
Switching to this syntax worked just fine:
IEnumerable<Foo> foos = connection.Table<Foo>().Where(
delegate(Foo foo)
{
return (foo.Timestamp.Year == year);
});
I am trying to use AddMonths in a query
List<Entities.Subscriber> items = (from s in context.Subscribers
where s.Validated == false && s.ValidationEmailSent == true && s.SubscriptionDateTime < DateTime.Now.AddMonths(-1)
select s).ToList();
But I recieve an error :
LINQ to Entities does not recognize the method 'System.DateTime
AddMonths(Int32)' method, and this method cannot be translated into a
store expression.
Is there a way I can use this function inside my query?
The simplest fix to this is to work out the time limit once before using LINQ:
DateTime limit = DateTime.Now.AddMonths(-1);
List<Entities.Subscriber> items = (from s in context.Subscribers
where s.Validated == false && s.ValidationEmailSent == true &&
s.SubscriptionDateTime < limit)
select s).ToList();
Or more readably IMO:
var items = context.Subscribers
.Where(s => !s.Validated &&
s.ValidationEmailSent &&
s.SubscriptionDateTime < limit)
.ToList();
There's no benefit in using a query expression here, and explicit comparisons with true and false are ugly IMO (unless your properties are of type Nullable<bool> of course).
Jon Skeet has already provided a simple fix, but if you want the DateTime.Now.AddMonths bit to run on the database, try the EntityFunctions.AddMonths method.
This is a more general approach that is especially useful when you cannot replicate the expression cheaply or correctly on the client.
You can change your code to:
DateTime oneMonth = DateTime.Now.AddMonths(-1)
List<Entities.Subscriber> items = (from s in context.Subscribers
where s.Validated == false && s.ValidationEmailSent == true && s.SubscriptionDateTime < oneMonth
select s).ToList();
You have to do this because AddMonth is a .NET function that can't be translated into SQL by Linq to Entities. Perform the calculation in your code and then use the resulting datetime will work.
Basically i want to merge two Iqueryable to one Iqueryable and then return the complete record set after my loop ends. It runs perfectly but in the end my objret have nothing but when i debug the loop obj have some records. wht im doing wrong
IQueryable<MediaType> objret = Enumerable.Empty<MediaType>().AsQueryable();
var typ = _db.MediaTypes.Where(e => e.int_MediaTypeId != 1 && e.int_MediaTypeId_FK == null).ToList();
for (int i = 0; i < typ.Count; i++)
{
IQueryable<MediaType> obj = _db.MediaTypes.Where(e => e.bit_IsActive == true && e.int_MediaTypeId_FK == typ[i].int_MediaTypeId);
IQueryable<MediaType> obj1 = _db.MediaTypes.Where(e => e.int_OrganizationId == Authorization.OrganizationID && e.bit_IsActive == true && e.int_MediaTypeId_FK == typ[i].int_MediaTypeId);
if (obj1.Count() > 0)
obj.Concat(obj1);
if(obj.Count() > 0)
objret.Concat(obj);
}
return objret;
Just like the other query operators, Concat doesn't change the existing sequence - it returns a new sequence.
So these lines:
if (obj1.Count() > 0)
obj.Concat(obj1);
if(obj.Count() > 0)
objret.Concat(obj);
should be
if (obj1.Count() > 0)
objret = objret.Concat(obj1);
if(obj.Count() > 0)
objret = objret.Concat(obj);
I'm not sure how well IQueryable is going to handle this, given that you're mixing LINQ to SQL (? maybe Entities) with Enumerable.AsQueryable, mind you. Given that you're already executing the queries to some extent due to the Count() calls, have you considered building up a List<T> instead?
(You don't need to execute the Count() at all - just call List<T>.AddRange(obj1) and ditto for obj.)
As jeroenh mentioned, ideally it would be nice to use a solution which could do it all that the database without looping at all in your C# code.
I think you should not do this with a for loop. The code you posted will go to the db for every single active mediatype twice to get Count() and additionally, twice to get actual results.
Checking the Count() property is not necessary: concatenating empty result sets has no additional effect.
Furthermore, I think what you're trying to achieve can be done with a single query, something along the lines of (not tested):
// build up the query
var rootTypes = _db.MediaTypes.Where(e => e.int_MediaTypeId != 1 && e.int_MediaTypeId_FK == null);
var activeChildren = _db.MediaTypes
.Where(e => e.bit_IsActive);
var activeChildrenForOrganization = _db.MediaTypes
.Where(e => e.int_OrganizationId == Authorization.OrganizationID && e.bit_IsActive);
var q = from types in rootTypes
join e in activeChildren
on types.int_MediaTypeId equals e.int_MediaTypeId_FK into joined1
join e in activeChildrenForOrganization
on types.int_MediaTypeId equals e.int_MediaTypeId_FK into joined2
select new {types, joined1, joined2};
// evaluate the query and concatenate the results.
// This will only go to the db once
return q.ToList().SelectMany(x => x.joined1.Concat(x.joined2));
I have the below LINQ Method I am trying to create. The issue seems to be the Second WHERE clause. I am getting this error -->
Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<MatrixReloaded.Data.CMO.tblWorkerHistory>' to 'bool'
I also had && there vs WHERE but I was getting a similar error. I don't NEED anything from tblWorkerHistories except the EndDate stuff.
There is a Many To Many relationship between the 2 tables with EnrollmentID being a FK on both.
public static DataTable GetCurrentWorkersByEnrollmentID(int enrollmentID)
{
using (var context = CmoDataContext.Create())
{
context.Log = Console.Out;
var currentWorkers = from enrollment in context.tblCMOEnrollments
where enrollment.EnrollmentID == enrollmentID
where enrollment.tblWorkerHistories.Where(a => a.EndDate == null || a.EndDate > DateTime.Now)
select
new
{
enrollment.CMONurseID,
enrollment.CMOSocialWorkerID,
SupportWorkerName = enrollment.tblSupportWorker.FirstName + " " + enrollment.tblSupportWorker.LastName,
SupportWorkerPhone = enrollment.tblSupportWorker.Phone
};
return currentWorkers.CopyLinqToDataTable();
}
}
This is the problem:
where enrollment.tblWorkerHistories.Where(/* stuff */)
Where returns a sequence... whereas you need something that will return a Boolean value. What are you trying to do with that embedded Where clause?
As Marc says, it could be that you just need an Any call instead of Where... but if you could explain what you're trying to do, that would make it a lot easier to help you. Note that Any does return a Boolean value, instead of a sequence.
EDIT: Okay, so in SQL you'd use a join, but you don't need an explicit join here because LINQ is implicitly doing that for you, right? If you're trying to find enrollments where any of the histories match the date, and you don't care about the histories themselves, then Any is indeed what you want:
var currentWorkers = from enrollment in context.tblCMOEnrollments
where enrollment.EnrollmentID == enrollmentID
where enrollment.tblWorkerHistories.Any
(a => a.EndDate == null || a.EndDate > DateTime.Now)
select ...
I suspect you mean .Any instead of .Where in the sub-query; the outermost .Where (i.e. the second where) expects a predicate expression, but yours is currently a selector - try:
where enrollment.tblWorkerHistories.Any(
a => a.EndDate == null || a.EndDate > DateTime.Now)