Check if a value is in a collection with LINQ - c#

I have a class "Employee", this has an IList<> of "TypeOfWork".
public class Employee
{
public virtual IList<TypeOfWork> TypeOfWorks { get; set; }
}
public class TypeOfWork
{
public virtual Customer Customer { get; set; }
public virtual Guid Id { get; set; }
public virtual string Name{ get; set; }
public virtual bool IsActive{ get; set; }
}
before saving, I'd lile to know if "typeofwid" (a Guid) is already in the "TypeOfWorks" collection.
I tried this :
var res = from p in employee.TypeOfWorks
where p.Id == new Guid("11111111-1111-1111-1111-111111111111")
select p ;
and tried this :
bool res = employee.TypeOfWorks.Where(f => f.Id == new Guid("11111111-1111-1111-1111-111111111111")).Count() != 0;
in the "Immediate Window" of Visual Studio but I receive the error : Expression cannot contain query expressions in both case
Do you have an idea ?
Thanks,

Just what the error says. You can't use LINQ queries in the Immediate Window because they require compilation of lambda functions. Try the first line in your actual code, where it can be compiled. :)
Also, to get this all done in one line, you can use the LINQ "Any" operator, like so:
if( ! employee.TypeOfWorks.Any(tow => tow.Id == theNewGUID) )
//save logic for TypeOfWork containing theNewGUID

How about this:
Guid guid = Guid.NewGuid("11111111-1111-1111-1111-111111111111");
var res = from p in employee.TypeOfWorks
where p.Id == guid
select p ;
The problem is constructing the guid - otherwise the linq queries should work

I think either of those work, actually. Keep in mind Visual Studio can't handle Linq Queries in the watch window either, so I suspect the error you saw is more of a Visual Studio problem than the code not working.

Try this code to get the count of typeofwork not initialized.
if(employee.TypeOfWorks
.Count(f => f.Id != new Guid("11111111-1111-1111-1111-111111111111")) != 0)
{
//do something
}

Related

Update model sort order [duplicate]

Any idea why the LINQ OrderBy is not working in following code, (have no errors but method does not sort ...)
First my own type
public class IQLinksView
{
public int id { get; set; }
public int catid { get; set; }
public int? viewed {get;set;}
public string name {get;set;}
public string desc {get;set;}
public string url {get;set;}
public string pic {get;set;}
public string cat {get;set;}
}
then query :
IQueryable<IQLinksView> newView =
from links in this.emContext.tbl_otherlinks
select new IQLinksView { id = links.pklinkid, catid =
links.tbl_catgeory.pkcategoryid, viewed = links.linkviewed, name = links.linkname,
desc = links.linkdesc, pic = links.linkpicture, url = links.linkurl, cat =
links.tbl_catgeory.categoryname };
Untill here all fine :-), but then
newView.OrderBy(x => x.viewed);
just changes nothing,... Page is loading results showing ... but no ordering ... sniff
i have Try with (creating a comparer object ... ):
newView.OrderBy(x => (Int32)x.viewed, new CompareIntegers());
same result, no ordering ...
I do have workarounds but just wondering what is missing ....
Any suggestions will be appreciated thanks a lot :-)
Don't throw away the return value. The OrderBy extension method is does not mutate the input. Try:
newView = newView.OrderBy(x => x.viewed);
There is no reason why that won't work, assuming the viewed value is correct. Also, make sure that OrderBy is after any operations (e.g. Distinct) which will ruin ordering.
Happy coding!
No-Tracking Queries
Consider use the asnotracking() after orderby() if the result is a readonly result.
Example:
query = query.OrderByDescending(x => x.Rating).AsNoTracking();

How to use a copy-constructor in a LINQ to Entities query?

I'm working on a Linq expression in which I get an object from a DBContext, and I want to make it a custom ViewModel object
my ViewModel receives as parameter an object obtained from the DBContext to work the information and return it completely
This is a little example
public class Obj1 // Object i get from database
{
public int id { get; set; }
public string Param { get; set; }
public string Param2 { get; set; }
public string Random { get; set; }
}
public class Obj2 //ViewModel
{
public string ParamFormateado { get; set; }
public string Random { get; set; }
public Obj2(Obj1 parametro)
{
ParamFormateado = parametro.Param + parametro.Param2;
Random = parametro.Random;
}
}
What I'm trying to do is get an Obj2 with a Linq expression who returns an Obj1 without transforming the information in the linq expression, since in my case it becomes a basically illegible expression
I was try something like this
Obj2 objeto = db.Obj1.Where(x => x.id == "0").Select(x => new Obj2(x)).FirstOrDefault();
Is it possible to perform a Linq query similar to the one I am proposing? since otherwise, I end up having extremely long Linq expressions to format this information, but what would be the best alternative in these cases?
You can't do that because only parameterless constructors are supported. But you can do it with Linq-To-Objects which can be forced with AsEnumerable:
Obj2 objeto = db.Obj1
.Where(x => x.id == "0")
.AsEnumerable() // <--- here
.Select(x => new Obj2(x))
.FirstOrDefault();
So only the filter with Where will be executed in the database, the remaining record(s) are processed in-process.
https://codeblog.jonskeet.uk/2011/01/14/reimplementing-linq-to-objects-part-36-asenumerable/
Dont do it with Linq like that. you have to create a method that takes obj1 as parameter, maps properties and then returns obj2. Or use Automapper from nuget repository.
do it like this
public obj2 Map(obj1 source)
{
var destination = new obj2();
destination.param1 = source.param1;
//
return destination;
}
if you want to pass a collection of objects then do just that and just foreach through the list and return a list of mapped objects. But i would advise you to use Automapper since it automates the proces and you dont have to write a long mapping code.

Error when performing OrderBy on a Sub-Property of an object

I am having problem in performing OrderBy on a sub-property of an Object.
I have two separate Models as listed below:
PersonModel:
public class PersonModel
{
public string Name { get; set;}
public DeptModel Dept { get; set; }
}
DeptModel
public class DeptModel
{
public int DeptId { get; set;}
public string DeptName { get; set;}
}
I had used automapper to map the relation between those two class and I am able to retrieve data properly.
After the data had been retrieved, I am trying to implement order by using linq on the DeptName object. Then it is showing an error "Object reference not set to an instance of an object."
The result is retrieving data as IList < PersonModel >. If Debug over here it is showing the correct data at this point.
Then I am performing the OrderBy on the retrieved data and it is crashing over here.
var tmp = result.OrderBy(x => x.Dept.DeptName).ToList();
I am not sure why I getting this error. Any suggestions on resolving the issue is greatly appreciated.
You need to make sure you are not using null in a default comparison. This is a simple example:
var tmp = result.OrderBy(x => ((x.Dept == null) || (x.Dept.Deptname == null)) ? "" : x.Dept.DeptName).ToList();
If you want a really nice solution though, you should implement your own Comparator See more here:
Use own IComparer<T> with Linq OrderBy

Merging Null int Column after joining

I want to merge, outer join the column "Count" from View_AssessmentCount list to View_Assessment. Of course Count will get an error because it is int and I wrote String.Empty. It's at this part where I specify where to outer join the null column "Count". But then again I don't know the right terms to Google this. Please help me expound on this.
public class AssessmentWithCount
{
public int Count { get; set; }
public String AssessmentName { get; set; }
public String AssessmentInitials { get; set; }
public Int16 id { get; set; }
}
public IEnumerable<AssessmentWithCount> GetAssessmentWithCount()
{
using (var context = new SQL_TA_SCOREBOARDEntities1())
{
var query = from a in context.View_Assessment
join b in context.View_AssessmentCount on a.AssessmentName equals b.AssessmentName into ab
from subA in ab.DefaultIfEmpty()
select new AssessmentWithCount
{
AssessmentName = a.AssessmentName,
Count = (subA == null ? String.Empty : subA.Count.ToString())
};
return query;
}
}
Updated post
Now my error is "The ObjectContext instance has been disposed and can no longer be used for operations that require a connection." when I DataBind this class. :(
Don't convert the database field to a string - just use it as-is:
Count = (subA == null ? 0 : (subA.Count ?? 0))
Regarding the error message... the using statement disposes your instance of SQL_TA_SCOREBOARDEntities1, so you need to get your data now, before leaving the method:
return query.ToList();
Here try this instead:
Count = SubA.Count ?? 0
Just had some issues like these and got help. :)
Sorry I can't comment as I have less than 50 reps.

Entity Framework select object based on filters accross multiple child collections

Assume I have the following domain (not my actual domain, but a trivial example)
public class ClassRoom
{
public int Id {get;set;}
public string Name {get;set;}
public virtual ICollection<Desk> Desks{get;set;}
public virtual ICollection<LunchBox> LunchBoxs{get;set;}
}
public class Desk
{
public int Id {get;set;}
public String Colour {get;set;}
public String Make {get;set;}
Public ClassRoom ClassRoom {get;set;}
}
public class LunchBox
{
public int Id {get;set;}
public String Colour {get;set;}
public int Volume {get;set;}
}
I would like to be able to query as follows
"Give me all the classes that have blue desks or green lunchboxes" returning a list of classes
I would have thought the code to be
var efClasses = (from d in myentity.ClassRooms
where ( (d.Desks.Colour == "blue")
|| (d.LunchBoxs.Colour == "green) )
select d).Distinct();
doing this gives me the error
Cannot convert lambda expression to type 'string' because it is not a delegate type
(obviously unhappy about the Colour, it expects a method here
so I changed it to this as an experiment
var efClasses = (from d in myentity.ClassRoom
where ( (d.Desks.Where(x=>x.Colour == "blue"))
|| (d.LunchBoxs.Where(x=>x.Colour == "green)) )
select d).Distinct();
But this wont compile either (In hindsight I had a feeling I was trying my luck on this.
I could go the other way around by changing my from to be myentity.Desks, and myEntity.Lunchboxs, and return two seperate lists of ClassRooms, and then find the union, but this will require 2 separate DB hits, and feels hacky
Instead of using count > 0, you can use Any
var efClasses = (from d in myentity.ClassRoom
where (d.Desks.Any(x => x.Colour == "blue") ||
d.LunchBoxs.Any(x => x.Colour == "green"))
select d);
Use Count >0 like this.
var efClasses = (from d in myentity.ClassRoom
where (d.Desks.Count(x => x.Colour == "blue") > 0
|| d.LunchBoxs.Count(x => x.Colour == "green") > 0)
select d);

Categories