my aim is to return result via left join by linq. The io.IsDefault can be null but insted of this I want to return MyStronglyTypeObj obj with the rest data.
context.Image.Where(i => i.IsActive == true) have 3 rows. one of those have isDefault null because this ImageId- (io => io.ImageId == i.ImageId) dosent exist in ImageObject
var test2 = (from i in context.Image.Where(i => i.IsActive == true)
from io in ImageObject.Where(io => io.ImageId == i.ImageId).DefaultIfEmpty()
select new MyStronglyTypeObj() { Alt = i.Alt, Caption = i.Caption, DisplayName = i.DisplayName, Extension = i.Extension, IsDefault = io.IsDefault, Height = i.Height, Width = i.Width, Name = i.Name });
// return 2 imgs - the 3rd one without isDefault (isDefault = null) wasn't added to collection.
var test = (from i in context.Image.Where(i => i.IsActive == true)
from io in ImageObject.Where(io => io.ImageId == i.ImageId).DefaultIfEmpty()
select i); // return 3 imgs
Is something obvious to me that I don't see? - perhaps I totally misunderstood the .DefaultIfEmpty() function
please help
DefaultIfEmpty() only affects empty collections, and causes that collection to return a single element with value default(T) (where T == collection type).
For example, using strings (note default(string) == null):
So based on the code you provided:
DefaultIfEmpty() is not a factor
The only other difference is the select statement, which doesn't really make sense
I'm guessing i is type MyStronglyTypeObj (based on properties matching)? I suspect there's another factor when you're running this code that you're not taking into account.
Try putting a breakpoint on that line, and viewing the results in the debugger.
Also, because LINQ uses deferred execution, this query code doesn't actually "run" until it gets consumed, and depending on when that happens, the source data can change (essentially, easily causing timing bugs if you're changing the source data somewhere else). Even more frustrating, this can cause this bug to disappear when you use a debugger and view the results in that, as it causes the code to execute sooner. You can avoid this by adding a .ToList() at the end of the line to cause the results to be executed immediately.
Related
I have the following statement with an Or condition. I am looking what would be the result when both conditions are true.
var result = db.Result.FirstOrDefault(x=>(x.ID==50||x.ID==60)&&x.Name="XYZ");
In a case where I have a row in the result table where both the conditions are true, i.e; x.ID=50 and x.ID=60. What would be the result of the query?
I have already tested to get the result in a test environment. But I wanted to make sure that the order of execution would always remain the same no matter what the size of the database is. As I have read that the where clause uses some sort of indexing for faster retrieval, what would be the course of execution of this statement.
The provided query is just a sample and the name ID has nothing to do with the unique identified of a table.
Question
How would the check be performed on the database? I would expect a result where it first checks if ID ==50 and on failure check if ID==60. If this is my expected result, would the query given above achieve my task?
Update after answer
I find it necessary to give a more clearer example so that the question is more understandable. (If this update makes the existing answers invalid, I am really sorry)
var result = db.result.firstordefault(x=>(x.foreignkeyid == someval|| foreignkeyid == 123)&& x.Name=="XYZ");
And my database sample
ID foreignkeyid Name
1 123 XYZ
2 somevalue XYZ
3 anothervalue XYZ
In this case when the query is executed the result would return the row with ID==1 , but I want row wiht ID==2 to be returned.
Worst case attempt to achieve the result
var result = new Result();
result =db.Result.firstordefault(x=>x.ID==somevalue&&x.name==xyz);
if(result==null)
var result = db.firstordefault(x=>x.ID ==123&& x.name==xyz);
Given this example of yours:
var result = db.result.firstordefault(x=>(x.foreignkeyid == someval|| foreignkeyid == 123)&& x.Name=="XYZ");
In which you want to prioritize the result where fk = someval (fk: foreign key), you can do the following:
db.set.OrderBy(x => x != someval) // false actually comes before true
.ThenBy(x => x != val2ndPriority)
.FirstOrDefault(x => (x.fk == someval ||
x.fk == val2ndPriority ||
x.fk == leastPriorityVal) &&
x.Name == "XYZ");
If you have a lot of "prioritized fk values", or if they are unknown at compile time, you can do:
var orderedEnum = db.set.OrderBy(x => x.Id);
foreach (var fk in fksByPriority)
orderedEnum = orderedEnum.ThenBy(x => x != fk);
var result = orderedEnum.FirstOrDefault(x => fksByPriority.Contains(x.fk) &&
x.Name == "XYZ");
How I would prefer it to look like:
Another different approach would be to get all possibly-relevant records and then run similar logic outside of the DB (your db Linq queries normally run smartly right inside the db):
var results = db.set.Where(x => x.Name == "XYZ" &&
fks.Contains(x.fk)).ToArray();
var highestPriorityResult =
results.OrderBy(x => fksByPriority.IndexOf(x.fk)).FirstOrDefault();
On a final note, I wish to say that your problem indicates a possibly flawed design. I can't imagine why you'd have this filtering-with-priority-foreign-key issue.
The following code shows how I am assigning data into IEnumerable<UnCompletedJobDetailsBO>.
There is a list (IEnumerable<UnCompletedJobDetailsBO>) that has another list (List<JobDetailsBO>), with that child list (List<JobDetailsBO>) having a list on it. But the AllocationDetailList only ever has one list item.
public IEnumerable<UnCompletedJobDetailsBO> GetControlDetails(DateTime startDate)
{
var controlDetails =
(from booking in db.BookingDetail
where booking.BookingDateTime >= startDate
orderby booking.DocketNo
select new UnCompletedJobDetailsBO()
{
CustomerName = booking.Customer.Name,
CompanyName = booking.CompanyDetail.Name,
JobList =
(from job in db.BookingJob.Where(x => x.BookingID == booking.BookingID) //get job list
select new JobDetailsBO()
{
JobID = job.JobID,
JobType = job.JobType,
ItemName = job.ItemName,
AllocationDetailList =
(from jobAllocationDetail in db.JobAllocation
join returnUnCollected in db.JobReturnUnCollected
on jobAllocationDetail.JobAllocationDetailID
equals returnUnCollected.JobAllocationDetailID
into returnJob
from returnUnCollected in returnJob.DefaultIfEmpty()
where (jobAllocationDetail.Booking.BookingID == booking.BookingID)
select new AllocationBO()
{
JobUnCollectedID = returnJob.JobUnCollectedID,
JobType = jobAllocationDetail.JobType,
CurrentStatus = jobAllocationDetail.CurrentStatus,
}).DefaultIfEmpty().ToList(),
}).DefaultIfEmpty().ToList(),
}).ToList();
return controlDetails;
}
I want to remove the JobList item if the inner list (AllocationDetailList) item satisfies the condition below. Sometimes AllocationDetailList may be null, so I check that also. But when I write below query, it does not remove that particular JobList item that satisfies the condition. Thanks in advance.
public List<UnCompletedJobDetailsBO> RemovePODFromSelectedList(
List<UnCompletedJobDetailsBO> unCompletedJobDetailsBO)
{
unCompletedJobDetailsBO
.SelectMany(y => y.JobList)
.ToList()
.RemoveAll(x => ((x.AllocationDetailList[0] != null) ?
x.AllocationDetailList[0].JobType == "D" &&
x.AllocationDetailList[0].JobUnCollectedID == null &&
x.AllocationDetailList[0].CurrentStatus == 5 :
x.AllocationDetailList.Count > 1));
return unCompletedJobDetailsBO;
}
Without a good, minimal, complete code example, I'm not sure that any performance concern can be addressed. It's hard enough to fully understand the question as it is, but without being able to actually test the code, to reproduce and observe a specific performance concern, it's hard to know for sure where your concern specifically lies, never mind how to fix it.
That said, from the code you posted, it is clear why items are not being removed from the list. The basic issue is that while the SelectMany() method does have the effect of allowing you to enumerate all of the elements from all of the different JobList objects as a single enumeration, the elements are enumerated as a new enumeration.
When you call ToList(), you are creating a whole new list from that new enumeration, and when you call RemoveAll(), you are only removing elements from that new list, not the lists from which they originally came.
You say you can get it to work with a for loop. I assume you mean something like this:
public List<UnCompletedJobDetailsBO> RemovePODFromSelectedList(
List<UnCompletedJobDetailsBO> unCompletedJobDetailsBO)
{
foreach (var item in unCompletedJobDetailsBO)
{
item.JobList.RemoveAll(x => ((x.AllocationDetailList[0] != null) ?
x.AllocationDetailList[0].JobType == "D" &&
x.AllocationDetailList[0].JobUnCollectedID == null &&
x.AllocationDetailList[0].CurrentStatus == 5 :
x.AllocationDetailList.Count > 1));
}
return unCompletedJobDetailsBO;
}
Note: there is no need to return unCompletedJobDetailsBO. That entire object is unchanged, never mind the variable. The only thing the code is modifying is each individual JobList object within the passed-in object's members. I.e. the above method could actually have a return type of void, and the return statement could be removed entirely.
It is possible you could speed the code up by removing the elements in a different way. The List<T>.RemoveAll() method is in fact reasonably efficient, with O(n) cost. But it still involves copying all of the data in the list after the first element that is removed (so that all the elements are shifted down in the list). If you have to have the list ordered, this may be as good as you can do, but if not, you could process the removal differently, or use a different data structure altogether, something unordered where removal of one or more elements costs less.
But again, without more details and without a good example to work with addressing that particular issue doesn't seem practical here.
The condition
x.AllocationDetailList[0] != null
will throw exception if there is no item in the AllocationDetailList. Instead you need to check
x.AllocationDetailList!=null && x.AllocationDetailList.Count>0.
Also .ToList() after SelectMany in your code will create a new list and items will be removed from that new list instead of unCompletedJobDetailsBO. You need to modify the remove function as below
unCompletedJobDetailsBO.ForEach(y => y.JobList.RemoveAll(x => ((x.AllocationDetailList != null && x.AllocationDetailList.Count>0)
?
x.AllocationDetailList[0].JobType == "D"
&& x.AllocationDetailList[0].JobUnCollectedID == null
&& x.AllocationDetailList[0].CurrentStatus == "5"
:
x.AllocationDetailList.Count > 1
)
));
I am wondering if something like this could be done(of course what I have written does not work but that's what I am essentially trying to achieve) .
var test = u.Owner;
a.Table.Where(u => test == true)
I have a linq query that I want to reuse(basically I got a query that I use 5 times) and the only thing that changes is what I am comparing against.
So in the above u.Owner is compared against true. In another query it would look the same but instead of u.Owner I might have u.Add == true or u.Edd == true.
So is there a way I can sort of reuse what I have. Of course in my code the query is a bit longer but I just shortened down.
Edit
Basically the whole query
List<Permission> clearence = user.PermissionLevels.Where(u => u.Id == Id &&( u.Add == permissionNeeded || u.Permission.Name == PermissionTypes.Owner)).ToList();
permissionNeeded == Enum
So my orignal way of doing it was u.Permission.Name == permissionNeeded so I compared the enum value to a string.
Now my db model has change and I need to check against 5 different permissions separately that are bools and not strings.
u.Add = true || u.Owner == true;
u.Edit = true || u.Owner == true;
u.Delete= true || u.Owner == true;
u.View= true || u.Owner == true;
Thats all changes for the entire query so that's why I am trying to make it into one query(just like I had it before).
So I am thinking of having a switch statement. The method still takes in a permissionNeeded(enum) I then go through and determine what clause I need and some how insert it into the query.
switch(PermssionNeeded)
{
case PermissionTypes.Add:
u.Add;
break;
// all other cases here.
}
Take advantage of the fact that Where can have any function taking type Table as a parameter and returning a boolean to create a function like:
public IQueryable<Table> QueryTables(Func<Table, bool> testFunction)
{
return a.Table.Where(testFunction).AsQueryable<Table>();
}
Edit: (in addition to edit to add AsQueryable above, which I earlier forgot)
If all you want to do is vary the boolean field used in the test, and you don't want to have to specify an entire function (which you're about to find out is much easier), you would need to use some reflection:
using System.Reflection;
public IQueryable<Table> QueryTables(PropertyInfo pi)
{
return a.Table.Where(t => (bool)(pi.GetGetMethod().Invoke(t, null))).AsQueryable<Table>();
}
To construct the PropertyInfo object, use something like:
PropertyInfo pi = typeof(Table).GetProperty("Owner");
I prefer the earlier method, but I did want to show that something like this is at least possible.
If you only want to specify the property you are checking you can do
public IEnumerable<Table> GetTables(Func<Table,bool> getValue)
{
return a.Table.Where(table => /*some common filter*/)
.Where(table => getValue(table))
}
var query = from u in uSrc join v in vSrc on u.ID equals v.RelatedUID
where v.Valid && u.Created < DateTime.UtcNow.AddDays(-365)
select u; // relatively complicated starting point.
var q1 = query.Where(u => u.Add); // must also have Add true
var q2 = query.Where(u => u.Test); // must also have Test true
var q3 = query.Where(u => u.ID < 50); // must also have ID < 50
And so on.
Edit:
Okay, so your starting query is:
List<Permission> clearence = student.PermissionLevels.Where(u => u.Id == Id &&( u.Add == permissionNeeded || u.Permission.Name == PermissionTypes.Owner)).ToList();
However, note that this creates a list, so any further work done on it will be a matter of Linq-to-objects. We'll come back to that in a minute, as it's sometimes good and sometimes not.
Now, if I understand you correctly, you need different sets for different cases, which you can do with your query as per:
var set0 = clearance.Where(u.Add = true || u.Owner == true);
var set1 = clearance.Where(u.Edit = true || u.Owner == true);
var set2 = clearance.Where(u.Delete= true || u.Owner == true);
var set3 = clearance.Where(u.View= true || u.Owner == true);
Now, this will work, but may not be the best approach. If we go back to the original query, we don't have to do ToList(), but can have:
IQueryable<Permission> clearence = student.PermissionLevels.Where(u => u.Id == Id &&( u.Add == permissionNeeded || u.Permission.Name == PermissionTypes.Owner));
Now, in the first case because we built a list we first got all values that matched the critera backed, and then stored it in memory, in clearance.
In the second case, clearance doesn't store any values at all, but instructions on how to get them.
The question is which is better to use. In the case where we are going to end up using the vast majority of the objects returned by the first query on its own, then there is a performance boost in using the list version, because they are loaded into memory only once, and then taken from memory without hitting the database again.
However, in most cases, it's better to do the second version for two reasons:
We hit the database in each case, but only retrieve the objects needed in that case.
We don't store anything in memory longer than necessary. Above a certain amount this is an important performance matter in itself.
The time to first item is faster this way.
We can further refine, for example if we do the following:
var trimmed = from set0 select new{u.Id, u.Permission.Name};
The we retrieve anonymous objects with Id and Name properties that are all we care about for a particular case, and not all of the relevant fields are retrieved from the database, or other source.
I've recently come to prefer a Dictionary over switch statements. You could store all your lambas in a Dictionary<PermissionNeeded, Func<User, bool>> that would look like this:
Dictionary<PermissionNeeded, Func<User, bool>> Permissions =
new Dictionary<PermissionNeeded, Func<User, bool>> {
{ PermissionNeeded.Add, u => u.Add }, // don't need to specify == true
{ PermissionNeeded.Edit, u => u.Edit },
...
etc
};
And you would call it like this:
var clearance = Permissions[PermissionNeeded.Add](user);
or maybe
var clearance = Permissions[PermissionNeeded.Add](user) && Permissions[PermissionNeeded.Edit](user);
or perhaps
var clearance = Permission[PermissionNeeded.Add](user) || Permissions[PermissionNeeded.View](user);
and so on. Even if you don't have a user object, I think this would still be valid and make the code pretty easy to read, and if you have to modify your functions, its all in the dictionary...
I have an asp.net application in which I am using linq for data manipulation. While running, I get the exception "Sequence contains no matching element".
if (_lstAcl.Documents.Count > 0)
{
for (i = 0; i <= _lstAcl.Documents.Count - 1; i++)
{
string id = _lstAcl.Documents[i].ID.ToString();
var documentRow = _dsACL.Documents.First(o => o.ID == id);
if (documentRow !=null)
{
_lstAcl.Documents[i].Read = documentRow.Read;
_lstAcl.Documents[i].ReadRule = documentRow.ReadRule;
_lstAcl.Documents[i].Create= documentRow.Create;
_lstAcl.Documents[i].CreateRule = documentRow.CreateRule;
_lstAcl.Documents[i].Update = documentRow.Update;
_lstAcl.Documents[i].UpdateRule = documentRow.UpdateRule;
_lstAcl.Documents[i].Delete = documentRow.Delete;
_lstAcl.Documents[i].DeleteRule = documentRow.DeleteRule;
}
}
}
Well, I'd expect it's this line that's throwing the exception:
var documentRow = _dsACL.Documents.First(o => o.ID == id)
First() will throw an exception if it can't find any matching elements. Given that you're testing for null immediately afterwards, it sounds like you want FirstOrDefault(), which returns the default value for the element type (which is null for reference types) if no matching items are found:
var documentRow = _dsACL.Documents.FirstOrDefault(o => o.ID == id)
Other options to consider in some situations are Single() (when you believe there's exactly one matching element) and SingleOrDefault() (when you believe there's exactly one or zero matching elements). I suspect that FirstOrDefault is the best option in this particular case, but it's worth knowing about the others anyway.
On the other hand, it looks like you might actually be better off with a join here in the first place. If you didn't care that it would do all matches (rather than just the first) you could use:
var query = from target in _lstAcl.Documents
join source in _dsAcl.Document
where source.ID.ToString() equals target.ID
select new { source, target };
foreach (var pair in query)
{
target.Read = source.Read;
target.ReadRule = source.ReadRule;
// etc
}
That's simpler and more efficient IMO.
Even if you do decide to keep the loop, I have a couple of suggestions:
Get rid of the outer if. You don't need it, as if Count is zero the for loop body will never execute
Use exclusive upper bounds in for loops - they're more idiomatic in C#:
for (i = 0; i < _lstAcl.Documents.Count; i++)
Eliminate common subexpressions:
var target = _lstAcl.Documents[i];
// Now use target for the rest of the loop body
Where possible use foreach instead of for to start with:
foreach (var target in _lstAcl.Documents)
Use FirstOrDefault. First will never return null - if it can't find a matching element it throws the exception you're seeing.
_dsACL.Documents.FirstOrDefault(o => o.ID == id);
From the MSDN library:
The First<TSource>(IEnumerable<TSource>) method throws an exception if source contains no elements. To instead return a default value when the source sequence is empty, use the FirstOrDefault method.
For those of you who faced this issue while creating a controller through the context menu, reopening Visual Studio as an administrator fixed it.
Maybe using Where() before First() can help you, as my problem has been solved in this case.
var documentRow = _dsACL.Documents.Where(o => o.ID == id).FirstOrDefault();
Trying my hand at ADO.Net data services. All the examples shows how to retrieve lists but how would you go about retrieving a single value? e.g. Product X's Price.
Here is the LINQ query i use:
var qry = (from p in
svcContext.Products
where p.ProductName == "Chair"
&& p.Colour == 1
select c) as DataServiceQuery;
Product returnedProd;
qry.BeginExecute(
(pr) => returnedProd = qry.EndExecute(pr).First(), null);
Here i try to retrieve the product and load it into a local variable, but the local var stays null.
Pretty sure, i'm doing it completely wrong :)...any help would be greatly appreciated.
It's not suppose to be
var qry = (from p in svcContext.Products where p.ProductName == "Chair" && p.Colour == 1 select p) where did you declare the c ?
Sorry was supposed to be
var qry = (from p in
svcContext.Products where
p.ProductName == "Chair" && p.Colour
== 1 select p) as DataServiceQuery< Product >;
First() should throw an exception if the result set is empty - are you sure the query is even executing?
You are not the first to get hit by the asynchronous nature of all silverlight outgoing requests.
In the lambda expression
(pr) => returnedProd = qry.EndExecute(pr).First()
you capture the local variable returnedProd but usually the thread that will spin off AFTER BeginExecute has been called will be too late. It will probably executed after the execution goes out of scope of the current method and the variable will be lost.
The solution is to use effectively the "returnedProd" to populate the UI or whatever you need to do IN the lambda expression. Something like :
(pr) => {
returnedProd = qry.EndExecute(pr).First();
MessageBox.Show("Retrieved record" + returnedProd.Id);
}
Otherwise useful answer for the community, I wish I had one a few weeks ago :(