I am getting the problem with "Include" in Entity Framework. Lets assume that I have two tables with foreign key relation.
var result = (from u in entity.Table1.Include("Table2")
join o in entity.Table2 on u.Column1 equals o.Column1
where u.Column2 == “abc” && u.Column3 == ‘xyz’
&& o.Column5 == organizationCode
select u).FirstOrDefault();
With the above query its not returning the Table2 object data in the result even though I have proper data in the database.
The issue i have found with above query is, if query is having "Include" as well as "Join", EF not considering "Include" tables. This is my assumption.
After spending some time I got the data by writing a dummy query below that. Please see the both queries below.
var result = (from u in entity.Table1.Include("Table2")
join o in entity.Table2 on u.Column1 equals o.Column1
where u.Column2 == “abc” && u.Column3 == ‘xyz’
&& o.Column5 == organizationCode
select u).FirstOrDefault();
var resultOrg = (from o in entity. Table2
where o.Column5 == organizationCode
select o).FirstOrDefault();
After executing both queries I am getting the Include (Table2) data in the result variable. In this case unnecessarily I am executing one query which I want to avoid.
Please suggest me where we are doing wrong.
You cannot use Include if you are using join. There is now way around that. Moreover what you are trying to do is filtering include which is also not possible.
You can do this:
var result = (from u in entity.Table1.Include("Table2")
where u.Column2 == “abc” && u.Column3 == ‘xyz’ &&
u.Table2.Any(o => o.Column5 == organizationCode)
select u).FirstOrDefault();
But it will include all Table2 entities to filtered Table1 entities. You cannot restrict included values to only those having some organization code.
To filter navigation properties you must use projection:
var result = (from u in entity.Table1
where u.Column2 == “abc” && u.Column3 == ‘xyz’ &&
u.Table2.Any(o => o.Column5 == organizationCode)
select new
{
Table1 = u
Table2 = u.Table2.Where(o => o.Column5 == organizationCode)
}).FirstOrDefault();
You must project either to anonymous type or custom type.
The reason why your second query works is automatic wiring of relations for tracked properties and it is another way how to filter relations but in such case this is enough:
var result = (from u in entity.Table1
where u.Column2 == “abc” && u.Column3 == ‘xyz’ &&
u.Table2.Any(o => o.Column5 == organizationCode)
select u).FirstOrDefault();
var resultOrg = (from o in entity. Table2
where o.Column5 == organizationCode
select o).FirstOrDefault();
Related
I have this kind of query:
var p = form p in db.table
where(p.Id == variable1 && p.proId == variable2 ...)
select p.Tolist();
and for eg. if variable 1 is null don't compare that condition in where clause just take the where clause
where (p.proId == variable2 ...)
Is there any way to do this . Thanks in advance.
Just simple like this:
where((variable1 == null || p.Id == variable1) && p.proId == variable2 ...)
Can't you just null check in the where clause?
where((variable1 == null || p.Id == variable1)
&& (variable2 != null && p.proId == variable2))
While the other answers here will work, you tagged your question entity-framework, and anytime you're writing LINQ-to-Entities, it's very important to have your IQueryable/IEnumerable boundary firmly in mind, because only fully IQueryable compliant code is efficiently convertible to SQL (and many times, e.g., string.Format, is not convertible at all).
var q = null != variable1
? from p in db.table
where p.Id == variable1
where p.proId == variable2
select p
: from p in db.table
where p.proId == variable2
select p;
Note that, if writing LINQ-to-Objects instead, the other answers given are much more efficient, concise, and readable:
var q = from p in someEnumerable
where null == variable1 || p.Id == variable1
where p.proId == variable2
select p;
Note: I left off the .ToList() to keep the query as an IQueryable (or IEnumerable) because there are so many times you actually wish to enumerate through the query only once, or project to something simpler before resolving the query (e.g., select p.Id). This is especially important in the case of L2E, because everything you do before the .ToList() (or .ToArray() or .Load()) is directly convertible to SQL, which is the most powerful way to use EF.
So I have a linq query, where s1.code comes from an object before this linq query.
var q1 = from cf in db.Control_Franchises
join t1 in db.Territories
on SqlFunctions.StringConvert((double)cf.FranchiseID).Trim()
equals t1.FranchiseID.Trim()
join cu in db.Control_Users on t1.FK_CompanyID equals cu.PrimaryCompanyID
join u in db.Users on cu.UserID.ToLower() equals u.Username.ToLower()
where cf.Status == "ACTIVE"
&& cf.FranchiseID > 1000
&& cu.UserType == "Franchisee"
&& cu.Status == "ACTIVE"
&& t1.Province == s1.Code
orderby cu.LastName ascending, cf.FranchiseID ascending
select new
{
FranchiseId = cf.FranchiseID,
Province = cf.StateCode,
DisplayName = cu.LastName + ", " + cu.FirstName,
UserId = u.PK_UserID
};
I have the same block of code but this time in my where clause, I changed the filter from using t1.Province == s1.Code to cf.StateCode == s1.Code
var q1 = from cf in db.Control_Franchises
join t1 in db.Territories
on SqlFunctions.StringConvert((double)cf.FranchiseID).Trim()
equals t1.FranchiseID.Trim()
join cu in db.Control_Users on t1.FK_CompanyID equals cu.PrimaryCompanyID
join u in db.Users on cu.UserID.ToLower() equals u.Username.ToLower()
where cf.Status == "ACTIVE"
&& cf.FranchiseID > 1000
&& cu.UserType == "Franchisee"
&& cu.Status == "ACTIVE"
&& cf.StateCode == s1.Code // DIFFERENT FROM ABOVE
orderby cu.LastName ascending, cf.FranchiseID ascending
select new
{
FranchiseId = cf.FranchiseID,
Province = cf.StateCode,
DisplayName = cu.LastName + ", " + cu.FirstName,
UserId = u.PK_UserID
};
Now the first query runs 10 times as fast as the second one.
How I am measuring the speed though, is the load time of my Edit Page, which in turn is loading a mvc tree view of the nodes. This query as well portions of a different query.
Now I'm trying to understand why my first query loads much faster and the only reasoning I can think of is because I am doing a condition on a table that will be joined, so rather then joining the entire "Territories" table with "Control_Franchises" I am only joining a portion of the "Territories" table.
Any thoughts?
Most likely the two different columns t1.Province and cf.StateCode are indexed differently in underlying data source (or one isn't at all)
Using the technique found on the MSDN article "How to: Perform Left Outer Joins (C# Programming Guide)", I attempted to create a left outer join in my Linq code. The article mentions using the DefaultIfEmpty method in order to create a left outer join from a group join. Basically, it instructs the program to include the results of the left (first) collection even if there are no results in the right collection.
The way this program executes, however, it does so as if the outer join has not been specified.
In our database, AgentProductTraining is a collection of courses our agents have taken. Normally you cannot enter a Course onto it's appropriate table without entering a corresponding value into the CourseMaterials table. However, occasionally this may happen, so we want to make sure we return results even when a Course is listed in AgentProductTraining without any corresponding information in CourseMaterials.
var training = from a in db.AgentProductTraining
join m in db.CourseMaterials on a.CourseCode equals m.CourseCode into apm
where
a.SymNumber == id
from m in apm.DefaultIfEmpty()
where m.EffectiveDate <= a.DateTaken
&& ((m.TerminationDate > a.DateTaken) | (m.TerminationDate == null))
select new
{
a.AgentProdTrainId,
a.CourseCode,
a.Course.CourseDescription,
a.Course.Partner,
a.DateTaken,
a.DateExpired,
a.LastChangeOperator,
a.LastChangeDate,
a.ProductCode,
a.Product.ProductDescription,
m.MaterialId,
m.Description,
a.Method
};
The MSDN example uses a new variable subpet:
var query = from person in people
join pet in pets on person equals pet.Owner into gj
from subpet in gj.DefaultIfEmpty()
select new { person.FirstName, PetName = (subpet == null ? String.Empty : subpet.Name) };
So you must use your own "subpet", I rewrote your code using the submat variable:
var training = from a in db.AgentProductTraining
join m in db.CourseMaterials on a.CourseCode equals m.CourseCode into apm
where
a.SymNumber == id
from submat in apm.DefaultIfEmpty()
where
(submat.EffectiveDate <= a.DateTaken || submat.EffectiveDate == null) &&
(submat.TerminationDate > a.DateTaken || submat.TerminationDate == null)
select new
{
a.AgentProdTrainId,
a.CourseCode,
a.Course.CourseDescription,
a.Course.Partner,
a.DateTaken,
a.DateExpired,
a.LastChangeOperator,
a.LastChangeDate,
a.ProductCode,
a.Product.ProductDescription,
MaterialId = (submat==null?-1:submat.MaterialId),
Description = (submat==null?String.Empty:submat.Description),
a.Method
};
I can't find the correct way to build an EF (4.1) query that will return the same result as this SQL containing a LEFT JOIN:
SELECT
s.id_service,
s.description,
x.id_service as isDisponible
FROM
role.service_disponible s
LEFT JOIN
role.service_disponible_x_ue x
ON s.id_service = x.id_service AND x.id_ue = 1 and flg_actif = '1'
In fact I'm just trying to obtain the complete list of services disponible (ServiceDisponible) adding a field that tell me if service is disponible for a specific entity (filtered with the id_ue) which information come from a many to many related table (ServiceDisponibleXUe).
My model is:
Ideally, I would like this query to return this viewModel object what is basically my serviceDisponible domain with one more field indicating the disponibility of the service.
public ServiceDisponibleViewModel(ServiceDisponible ServiceDisponible, bool isDisponible)
{
this.serviceDisponible = serviceDisponible;
this.isDisponible = isDisponible;
}
What I have so far is this query but the syntax is invalid:
services = context.ServiceDisponible
.Select(a => new ServiceDisponibleViewModel
{
c => new ServiceDisponible
{
id_service = a.id_service,
description = a.description
},
isDisponible = a.ServiceDisponibleXUe
.Any(b => b.flg_actif && b.id_ue == idUe)
}).ToList();
Try this:
ServiceDisponibleViewModel services =
from sd in context.ServiceDisponible
from sdx in context.ServiceDisponibleXUe
.Where(x => x.id_ue == 1 && flg_actif == '1' && x.id_service == sd.id_service)
.DefaultIfEmpty()
select new ServiceDisponibleViewModel(
new ServiceDisponible
{
id_service = sd.id_service,
description = sd.description
},
sdx.id_service
);
Having SQL as example often makes one jump to a join in linq. But using navigation properties produces much more succinct syntax:
from sd in context.ServiceDisponible
from sdx in sd.ServiceDisponibleXUes.Where(x => x.id_ue == 1
&& x.flg_actif == "1")
.DefaultIfEmpty()
select new
{ sd.id_service,
sd.description,
isDisponible = sdx.id_service
};
(I couldn't help using the plural form of ServiceDisponibleXUe which imo is more clear).
I want to write if condition inside where clause. because if first name or last name is null I don't wani to add it in where clause . other wise I want to add it.
so I write
var query1 = from opv in _opvRepository.Table
join o in _orderRepository.Table on opv.OrderId equals o.Id
join gr in _graduandRepository.Table on opv.graduand_id equals gr.graduand_id
join pv in _productVariantRepository.Table on opv.ProductVariantId equals pv.Id
join p in _productRepository.Table on pv.ProductId equals p.Id
where (opv.ceremony_id == ceremony_id) &&
(!o.Deleted) && (opv.IsHireItem == true) &&
(!p.Deleted) &&
(!pv.Deleted) && (opv.ceremony_id == ceremony_id)
// group opv by opv.OrderId into g
select new
{
opvTable = opv,
grTable = gr,
};
// This is not working. I have problem in here. How to add this??
if (!String.IsNullOrEmpty(Fname))
query1 = query1.Where(grTable = > grTable.first_name == Fname);
var result = query1.ToList().Select(x =>
{
return new HireItemReportLine()
{
OrderId = x.opvTable.OrderId,
OrderDate=x.opvTable.Order.CreatedOnUtc,
Amount= x.opvTable.Order.OrderSubtotalExclTax,
PaymentMethod = x.opvTable.Order.PaymentMethodSystemName,
paidDate = x.opvTable.Order.CreatedOnUtc,
Fname = x.grTable.first_name,
MName = x.grTable.middle_name,
LName = x.grTable.last_name,
};
}).ToList();
What is the wrong with my cording??
Note that your original query selects an anonymous type with two properties: opvTable and grTable. So, you need to use one of those properties in the subsequent Where clause, like this:
query1 = query1.Where(item => item.grTable.first_name == Fname);