Entity Framework include items only by condition [duplicate] - c#

This question already has answers here:
EF: Include with where clause [duplicate]
(5 answers)
Closed 6 years ago.
I need my context to include the sonns by a condition, I need the rows that not deleted (logical delete).
I understood that I cannot add a condition to the include; so I want to filter the context, but it's not working.
var aa = ctx.aa
.Include(t => t.vari)
.ToList()
.FirstOrDefault();
ctx.vari.Where(bi => bi.ID == 10 && bi.Deleted == 1).ToList();
Thanks!

As codelahiru && hbulens pointed out, you missed the bi for ID.
Disclaimer: I'm the owner of the project Entity Framework Plus
The Query IncludeOptimized feature allows to filter with include and optimize the query performance at the same time (Support EF5, EF6)
var aa = ctx.aa
.IncludeOptimized(t => t.vari.Where(bi => bi.ID == 10 && bi.Deleted == 1))
.FirstOrDefault();
Documentation: EF+ Query IncludeOptimized

This isn't going to be the most performant query. It would be better to drop the ToList()
var aa = ctx.aa.Include(t => t.vari).ToList().FirstOrDefault();
// You missed the variable before ID
ctx.vari.Where(bi => bi.ID == 10 && bi.Deleted == 1).ToList();

Related

IN condition in LINQ to replace multiple OR conditions [duplicate]

This question already has answers here:
Linq to SQL how to do "where [column] in (list of values)"
(6 answers)
Closed 6 years ago.
I have an entity framework query as shown below. Here I am trying to find entities for which there is no fax information for primary and secondary users. I am using two person_role_cd conditions using “OR”.
What is the best LINQ way to make the same logic with something like SQL “IN” condition? For example, p.person_role_cd IN (“Primary”, “Secondary” )
query = query
.Where(l => l.loan_documents
.FirstOrDefault(d => d.document_type_cd == “Application”)
.loan_persons.Any(p =>
(
p.fax_no != null
&&
(
p.person_role_cd == “Primary”
||
p.person_role_cd == “Secondary”
)
)
) == false
);
First create an array with all strings you want to check against.
var targetList = new[] {"Primary", "Secondary"};
Then Replace your OR condition with
targetList.Contains(p.person_role_cd);
Caveat: Doing stuff like this causes problems with Linq to Entities
That said, the first thing that comes to mind is use a List with Contains (which is basically what the provided SQL does)
List<string> roles = new List<string>() { "Primary", "Secondary" };
query = query
.Where(l => l.loan_documents
.FirstOrDefault(d => d.document_type_cd == “Application”)
.loan_persons.Any(p => p.fax_no != null && roles.Contains(p.person_role_cd));
Couldn't quite tell where your negation belongs, left as exercise to the reader. The reason it may not work with Linq to Entities is that translating List.Contains (especially off of a local variable) to SQL is the kind of task it likes to give up on. If your types are literally two items, I would just keep the condition as is (apart from considering an enum for my types instead of strings)

Is there a difference in speed between multiple where clauses vs one where clause with multiple parameters C# IQueryable [duplicate]

This question already has answers here:
LINQ: differences between single Where with multiple conditions and consecutive Wheres with single condition [duplicate]
(2 answers)
Closed 6 years ago.
My question is if there is any difference in speed between this query
query.Where(i => (i.FirstName.Contains(firstname) || string.IsNullOrEmpty(firstname)) &&
(i.LastName.Contains(secondname) || string.IsNullOrEmpty(secondname)) &&
(i.DateOfOrder == date || date == default(DateTime)));
and this code:
if (!String.IsNullOrEmpty(firstname))
{
query = query.Where(i => i.FirstName.Contains(firstname));
}
if (!String.IsNullOrEmpty(secondname))
{
query = query.Where(i => i.FirstName.Contains(firstname));
}
if (date!=default(DateTime))
{
query = query.Where(i => i.DateOfOrder==date);
}
Edited, thanks for the answers.
I guess second code should be like below:
if (!String.IsNullOrEmpty(firstname))
{
query = query.Where(i => i.FirstName.Contains(firstname));
}
if (!String.IsNullOrEmpty(secondname))
{
query = query.Where(i => i.FirstName.Contains(firstname));
}
if (date!=default(DateTime))
{
query = query.Where(i => i.DateOfOrder==date);
}
but in any case, you may check the final sql query generated and compare them instead.
to get the sql query, you can
write the sql to console by calling dbCtx.Log = Console.Out
profile your sql server and see what queries come in

Best way to compare date in Entity Framework

I am using date in where clause in Entity Framework and getting following error:
It is due to the below code:
var entity = dbContext.MyTable
.Where(w => w.PId = 3 && w.CreatedOn.Date == mydate.Date)
.First();
If I convert data into list using .ToList(), then compare to date, it will work fine but if I do so then it will pull data first into code then filter it out. Please help me out with this issue. Currently I am using a stored procedure to resolve the issue but really want this to work.
You can use DbFunctions.TruncateTime canonical function like this
var entity = dbContext.MyTable
.Where(w => w.PId == 3 && DbFunctions.TruncateTime(w.CreatedOn) == mydate.Date)
.First();
This is how I ended up doing Date search when I had to consider time (Hour and Minutes portion) also
var entity = dbContext.MyTable
.Where(
x => x.CreatedOn.Year == mydate.Year
&& x.CreatedOn.Month == mydate.Month
&& x.CreatedOn.Day == mydatee.Day
&& x.CreatedOn.Hour == mydate.Hour
&& x.CreatedOn.Minute== mydate.Minute
).FirstOrDefault();
you cannot compare dates directly by using .Date for this you have to use DbFunctions or EntityFunctions.
I prefer to use DbFunctions
You can use it as given below:
var entity = dbContext.MyTable
.Where(w => w.PId = 3 && DbFunctions.TruncateTime(w.CreatedOn) == DbFunctions.TruncateTime(mydate))
.First();
EF doesn't currently support translating all granular operations on objects in LINQ to an SQL query (which is what happens prior to that ToList() operation). Some things are (such as .Contains() on primitive collections). But not all things.
So, while you may have expected the query to translate to various "DATEPART" comparisons in the SQL statement, it's just not supported. You have to change your LINQ to accommodate it a bit.
One way is to evaluate the 24-hour range. This will work on either side of the ToList():
DateTime minDate = new DateTime(mydate.Date.Year, mydate.Date.Month, mydate.Date.Second);
DateTime maxDate = minDate.AddSeconds(86399);
var entity = dbContext.MyTable
.Where(w => w.PId = 3 && w.CreatedOn >= minDate && w.CreatedOn <= maxDate).First();

Determine if LINQ Enumerable contains object based on a condition? [duplicate]

This question already has answers here:
Linq Contains method for a object
(4 answers)
Closed 10 years ago.
I have an IEnumerable<Project>
I want to know if this list has any element Project.ID == someID.
Is there a way to do that?
Yes, you want to use the Any method (documentation).
IEnumerable<Project> projects = SomeMethodReturningProjects();
if(projects.Any(p => p.ID == someID))
{
//Do something...
}
You can use the Any() extension method.
var hasAny = projectList.Any(proj => proj.ID == someID);
Or, if you want to get that record, you can use FirstOrDefault():
var matchedProject = projectList.FirstOrDefault(proj => proj.ID == someID);
This will return null if it finds nothing that matches, but will pull the whole object if it does find it.
Using
projects.Any(p => p.ID == someID)
returns true (a boolean) if the predicate matched for any element.
Yes, use the Any extension method:
list.Any(p => p.ID == someID);

Where clause on collection

I'm using the BAGA code from Julie Lerman's DbContext book. I want to recreate the following SQL query in LINQ and put the results in a List collections and am having problems.
http://learnentityframework.com/downloads/
SELECT * FROM baga.Locations d
LEFT JOIN Lodgings l ON d.LocationID = l.destination_id
WHERE d.Country = 'usa'
AND (l.MilesFromNearestAirport > 5 or l.MilesFromNearestAirport is null)
So, in English, get all locations (destinations) that are in the USA and include all the related lodgings where MilesFromNearestAirport > 5
The syntax doesn't compile but I was hoping for something similar to below
var dests = context.Destinations
.Where(d => d.Country == "USA" && d.Lodgings.Where(l => l.MilesFromNearestAirport > 5))
.Select(d => d)
.ToList();
Any ideas?
As #Sampath says, this is normally done with navigation properties but I believe that his code does not exactly do what you want. This (I think) is closer:
var dests = context.Destinations
.Where(d => d.Country == "USA")
.Select(d =>
new { d,
RemoteLodgings = d.Lodgings
.Where(l => l.MilesFromNearestAirport > 5)}
.ToList();
But it still does not do what you want if I take your requirement to the letter. You want the location with the lodgings included, i.e. the navigation properties loaded partly. This can be convenient when the entities are to be serialized and sent to a (web) client in one package. (Although the method above would be OK for that too).
But it is possible to make a collection with partly loaded navigation properties.
The book, at page 40, shows how you can partly load navigation properties of a single entity (in short: context.Entry(entity).Collection(e => e.Children).Query().Where(condition). But as said, that's only one instance. It's not the best method to do that for a collection of entities.
The funny thing is (as a colleague of mine found out), you can easily do it for a collection of entities by loading the required collection elements into the context separately:
var lodgings = context.Lodgings
.Where(l => l.MilesFromNearestAirport > 5
&& l.Destination.Country == "USA")
.ToList();
Now if you loop through context.Destinations.Where(d => d.Country == "USA") you will see that their lodgings are loaded with the ones ">5". Probably because at this point EF executed relationship fixup. (Lazy loading disabled, because lazy loading will fully load the navigation properties).
Edit (after your comment)
I couldn't agree more when you say it is a bit of a hack. Actually, I forgot to mention that in the first place. The problem is that the whole mechanism collapses when lazy loading happens to be activated by someone who's not aware of the what the code is for. I don't like code that depends on the state in a way that is not obvious. So I would always prefer the first approach.
Normally this is done using navigation properties which are loaded when you get the entity.
However you can also do this with the following:
(from d in baga.Locations
from l in Lodgings
where (d.LocationID == l.destination_id)
where (d.Country = 'usa' && (l.MilesFromNearestAirport > 5 || l.MilesFromNearestAirport == null))
select d)
.ToList();
I hope this will help to you.
How about using the LINQ join?
var res = from d in context.Destinations
join l in context.Lodgings on d.LocationID equals l.destination_id
where (l.MilesFromNearestAirport > 5 || l.MilesFromNearestAirport == null)
&& d.Country = "usa"
select new {
Destination = d,
Location = l
}

Categories