I'm not used with linq. I use EF 4.0. I'm always using lambda expression to get my data like this:
List<User> users = db.Users
.Include(u => u.Licences)
.Include(u => u.Licences.Select(l => l.LicenceProducts.Select(lp => lp.Product)))
.Include(u => u.UserAddress)
.Include(u => u.Contact)
.Include(u => u.User2)
.Include(u => u.SupportProducts)
.Where(u => u.Type != (int)UserType.Admin)
.OrderBy(u => u.Name)
.ToList();
Unfortunately, it takes a lot of time to execute. So, I want to change it by using left joins but I'm not understanding correctly the way joins are working in Linq.
Here's what I tried:
users = from user in db.Users
join licence in db.Licences on user.UserID equals licence.UserID
join licenceProduct in db.LicenceProducts on licence.LicenceID equals licenceProduct.LicenceID...;
The type that it returns, is not the same as it was previously (List)
I also tried this but I have the same problem
users = db.Users
.Join(db.Licences, lic => lic.UserID, user => user.UserID, (user, lic) => new { user, lic })
Joins don't do the same as Include. Includes tell EF to populate associated navigation properties off the entity that's in the main query. Joins, however, only execute a SQL joins, but don't populate anything.
You typically use joins if you want to filter on properties in child or parent objects. Like join c in Contacts ... where c.Name == "..." – this only returns Users without any contacts populated. The SQL SELECT clause only contains User columns. (Well, assuming you only select distinct users).
Includes also produce SQL joins, but at the same time put all columns of the included entities in the SELECT clause. The query result set is used to materialize all included entities. When there are many Includes, this result will blow up incredibly in width and length. In width, because it selects all columns of all included entities. In length because each included child collection multiplies the result set by its number of rows.
Therefore it is recommended to have no more than three Includes. So I think you have to reconsider the number of Includes you really need. It's probably much more efficient to load associated entities in separate queries.
The joins you are using are inner joins, not left joins. You can use DefaultIfEmpty() to turn them into left joins, as described here: http://msdn.microsoft.com/en-us/library/vstudio/bb397895.aspx
Also, note that using linq you are creating a query, not a list. The query only gets executed when the results need to be retrieved. You can call ToList() to do this. In general, if you are using LINQ for retrieving data it is important to read about deferred execution (good explanation here: http://blogs.msdn.com/b/charlie/archive/2007/12/09/deferred-execution.aspx), otherwise the data you get may not be what you are expecting if it changes between the time the query is created and the time that it gets executed.
Also, for that many includes I think that using a stored procedure be easier.
Related
I'm facing an issue with Entity Framework Core in C#. I have created a function to return the list of Organisation from my database. For each organisation, I have two tables:
OrganisationUser: the link with Organisation is the OrganisationId. This table is linked to the Licence table with the LicenceId
Invitation the link with Organisation is the OrganisationId. This table is linked to the Licence table with the LicenceId
If I run the query I received, as I expected, the list of organisations with all details.
public IQueryable<Organisation> GetOrganisationsByBillingDay(int billingDay)
{
return _context.Organisation
.Include(org => org.OrganisationUser)
.ThenInclude(usr => usr.License)
.Include(org => org.Invitation)
.ThenInclude(i => i.License)
.Where(o => o.BillingDay == billingDay);
}
In this list the organisation that doesn't have any records in OrganisationUser or Invitation are excluded.
How is it possible to include them? Is there a diffrent way than writing a query with Linq?
Update
If you look at the query Linq creates it ia a left join.
The configuration is
builder.Services.AddDbContext<BillingContext>(options =>
options.UseSqlServer(configuration.GetConnectionString("BillingDatabase"),
providerOptions => providerOptions.EnableRetryOnFailure()
));
Last Update
As you can see in the screenshot, Linq performs left join queries. I have now what I'm looking for. The problem was in the data not in the code.
If it is optional, then your navigation property will either be null or an empty collection depending upon what the cardinality of relationship is. There is nothing special you need to do as the join is implied by Include() but not explicitly specified by the user in the query itself.
The most likely issue is your relationship definition. Can you share your model config?
Our company is currently using Entity Framework Net Core 2.2 with Sql Server
Trying to find all Distinct customers who purchased a certain Product Input Parameter .
The following EF Linq query was written to get the distinct Customers.
Later another question came up, how do we get more (navigation) properties of customer? Should Include be placed Before the Where or After the Where? Does it matter? When running the SQL Profiler, it noted no difference in the queries. I just wanted to be sure in some cases does the location of Include here matter?
select distinct c.customerName
from dbo.customer customer
inner join dbo.Transactions transaction
on transaction.customerid = customer.customerid
inner join dbo.Purchases purchases
on purchases.PurchaseId = transaction.PurchaseId
inner join dbo.Product product
on transaction.ProductId = product.ProductId
where tra.BKProduct = #ProductInput
Original Solution: C# Entity Framework: Linq Filter on GrandChildren and Conduct a Select on the Parent
var customerData = db.Customer
.Where(p => p.Transactions.SelectMany(c => c.Purchases).Select(gc => gc.Product.Where(gc => gc.BKProduct == ProductInput).Any());
Another question came up, we need to get more (navigation) properties of Customer.
Alternative 1:
var customerData = db.Customer
.Include(c=>c.CustomerType)
.Include(c=>c.CustomerAddress)
.Where(p => p.Transactions.SelectMany(c => c.Purchases).Select(gc => gc.Product.Where(gc => gc.BKProduct == ProductInput).Any());
Alternative 2:
var customerData = db.Customer
.Where(p => p.Transactions.SelectMany(c => c.Purchases).Select(gc => gc.Product.Where(gc => gc.BKProduct == ProductInput).Any())
.Include(c=>c.CustomerType)
.Include(c=>c.CustomerAddress)
In this specific case, it probably does not matter.
Since c# "Include" is about the SELECT and the JOIN of the generated sql.
However, you do not want to use the "it does not matter" as a blanket statement.
See here answer below (and overall question and other answers).
Does the order of LINQ functions matter?
When you start putting in things like Where and OrderBy, the order-of-the-operations can matter.
Always look at the generated sql and ask yourself "does it look reasonable"? (Which you already did from your question :) ..I mention primarily this for future readers)
So in this specific case, it is a preference. I typically put .Where
last. So your first example would match my personal preference.
And for some "further investigation", check out something like : https://weblogs.asp.net/dixin/introducing-linq-3-waht-is-functional-programming
I am using linq-to-nhibernate with fluent (c#), and I want to do the following:
I have two IQueryable interfaces, relations and documentsrelations.
The relations object contain a list of enterprises and the documentsrelations object contain a second list of enterprises.
I want to generate a new list of enterprises that contains the list of enterprises (relations) minus the second list of enterprises (documentsrelations).
In sql I would try with an outer join, but I don't know how to do with this.
**** DECLARATIONS ****
IQueryable<EnterpriseRelation> documentsrelations =
shared_doc.SharedIn.AsQueryable();
var relations = EnterpriseRelationService
.QueryRelationsForEnterprise(LoggedUser.ActiveAsEnterprise)
.Where(x => x.ContactingEnterprise.NIF == LoggedUser.ActiveAsEnterprise.NIF);
relations is also an IQueryable<EnterpriseRelation>.
I tried multiplied things, but it always tells me that it is not supported.
Some help?
Thanks!
Supposing your entity primary key is Id, have you tried something like below?
var relations = EnterpriseRelationService
.QueryRelationsForEnterprise(LoggedUser.ActiveAsEnterprise)
.Where(x => x.ContactingEnterprise.NIF == LoggedUser.ActiveAsEnterprise.NIF)
.Where(x => !documentsrelations.Select(dr => dr.Id).Contains(x.Id));
Note:
Using .AsQueryable() as you do in your question is most of the time a mistake. If SharedIn is not actually a queryable instance, it will just convert it to a linq-to-object queryable, executing in memory, not in database. And for your case, there are no need to have it as a queryable anyway, at least with my answer above, and unless it is already a queryable awaiting execution in db.
If my answer fails, try again without your AsQueryable call on SharedIn.
I am surprised I cannot find a solution for this on the web, but wording the search terms was a bit difficult. The question I have is about generating entity SQL that only returns the needed columns in a group join using Lambda syntax.
The following is a "toy" example. I am not joining on two entities, rather on an enumerated list and an entity. And tunnelling is not an acceptable answer. I need to apply this to a much larger problem using a group join and select many.
var result1 = clientprofiles.Join(Context.Adjusters,
c => c.AdjusterId,
a => a.AdjusterId,
(c, a) => new {a.ClientAccountId}).ToList();
Using Julie Lehrman's Entity profiler, I see that the query is being generated to select every record in the rows that meet the join criteria. How do I pare it down so it only selects the ClientAccountId field in this example?
You can project a set of columns on any select from the context, so in your case you can constrain the Context.Adjusters parameter by using
Context.Adjusters.Select(a=> new { a.ClientAccountId })
to constrain the query to just the single column
If you do an nHiberante Linq query and you want to eager load the related objects.
Where do you put the Fetch or the FetchMany ?
Like this:
_session.Query<Entity>()
.Where(x => x.IsSomething)
.FetchMany(x => x.Children);
Or like this:
_session.Query<Entity>()
.FetchMany(x => x.Children)
.Where(x => x.IsSomething);
I want to know the best order to place the Fetch or FetchMany (For performance). Or does the order even matter? When I use entity framework i always write the includes first, is this the same case in nHibernate?
We use the specification pattern with nHibernate. So is it smart to put the Fetch or FetchMany in the specifications?
Doesn't matter. IQueryable is just a query statement and Fetch(), FetchMany() is just a setting on the Nhibernate query which enlarge the query to return more data so that you don't perform lazy loading later on. The query is not sent to the database until you call ToList(), Single() etc. The linq query is then transformed into a sql query which will contain more joins and columns and THEN it is sent to the database server.
The following query will do a "similar" join when fetching the entity + children but here I map it into a anonymous object:
_session
.Query<Entity>()
.Where(x => x.IsSomething)
.Select(x => new { MyEntity = x, MyEntitiesChildren = x.Children });