Linq Query with multiple joins and multiple conditions - linq

I am using Telerik Data Access to perform OR mapping.
I am trying to use Linq for performing a join query but not sure how to proceed correctly.
The original sql query is given by:
'SELECT O.OPS_LEG_ID, O.ATD_DATE, O.DEP_AIRPORT_ACT, O.ARR_AIRPORT_ACT, O.ATA_DATE, '+
'O.FL_LOG_ATD_DATE, O.FL_LOG_ATA_DATE, O.FL_LOG_DEP_AIRPORT, O.FL_LOG_ARR_AIRPORT, '+
'O.FL_NB, O.DESIGNATOR, O.FL_LOG_ID, O.FL_LOG_STATUS '+
'FROM CREW_ROT_ROLE CR, OPS_LEG O, CREW_ROLES R, CREW_PAIRING_CMP CP '+
'WHERE CR.ROLE_CDE = R.ROLE_CDE '+
'AND CR.CREW_ROTATION_ID = CP.CREW_ROTATION_ID '+
'AND CP.OPS_LEG_ID = O.OPS_LEG_ID '+
'AND CR.CREW_CDE = :CREW_CDE '+
'AND O.ATD_DATE >= :D_FROM '+
'AND O.ATD_DATE <= :D_TO '+
//'AND R.ROLE_TYPE = 0 '+
'ORDER BY O.ATD_DATE
The corresponding Entities have been generated from the SQL tables. I am now trying to build the equivalent Linq query, which does not seem to work:
var results = from opsLeg in dbContext.OPS_LEGs
from crewRotationRole in dbContext.CREW_ROT_ROLEs
from crewRole in dbContext.CREW_ROLEs
from crewPairingComponent in dbContext.CREW_PAIRING_CMPs
where crewRotationRole.ROLE_CDE == crewRole.ROLE_CDE
&& crewRotationRole.CREW_ROTATION_ID == crewPairingComponent.CREW_ROTATION_ID
&& crewPairingComponent.OPS_LEG_ID == opsLeg.OPS_LEG_ID
&& crewRotationRole.CREW_CDE == userId
select new { OpsLegId = opsLeg.OPS_LEG_ID,
Designator = opsLeg.DESIGNATOR,
FlightNumber = opsLeg.FL_NB
};
Trying the previous query, raises an exception:
"Identifier 'ROLE_CDE' is not a parameter or variable or field of
'FlightLogEntities.OPS_LEG'. If 'ROLE_CDE' is a property please add
the FieldAlias or Storage attribute to it or declare it as a field's
alias."
Not sure how to proceed. What would be the correct query using Linq joins? Thanks!

If you are using a ORM like Entity framework, then the conceptual model would be mix of classes, which would provide a object centric view of data.
So, you would be using the Linq on Objects and in that case you need not write queries for joins as we do in SQL for a database. Conceptual model would contain objects which would be having relationships using navigational properties, and to access navigational properties you can access them as a property of object.
For e.g if there are 2 tables in Database, Customer & Orders. Following SQL statement will return all Orders for Customer number 1:
SELECT Customers.CustomerName, Orders.OrderID
FROM Customers
INNER JOIN Orders
ON Customers.CustomerID=Orders.CustomerID
Where Customers.CustomerID = 1
If we use the EF to generate to generate the conceptual model from Database, we would get class for Customer and Order and Customer class would have a property of ICollection. So, if you need the same results as the SQL query above, you would do it in following way
var CustomerOne = context.Customers.Where(x => x.CustomerID == 1);
var ordersForCustomerOne = CustomerOne.Orders;

You can try something like
var k = from r in dataContext.Order_Details
join t in dataContext.Orders on r.OrderID equals t.OrderID
select r.OrderID ;

Related

Dynamic Linq core

Hi I am using a Jqwidgets Grid to display my data. It has a build in possibility to use filters but if you filter your records on the server side you have to build your own query. As I am working with Linq I thought to use the Dynamic Linq Library for Asp net core. Problem is there are not many examples or explanations how to do this. But I am busy for days now and not getting very far.The way I am setup; I have a normal Linq query:
var Mut = from M in _DB.Mutations
join S in _DB.Shifts on M.ShiftId equals S.ShiftId
join U in _DB.RoosterUsers on M.UserId equals U.RoosterUserId
join D in deps on M.UserId equals D.UserId
join DD in _DB.Departements on D.DepartementID equals DD.DepartementId
select new MutationModel
{
MutId=M.MutationId,
Naam=U.FirstName + " " + U.LastName,
UserId=M.UserId,
Departement= DD.DepartementName,
MutationType = S.publicName,
MutationGroup = S.ShiftType.ToString(),
DateTot =M.DateTill,
TijdVan=M.DateStartOn,
TijdTot=M.DateTill,
Status=CreateStatus(M.Tentative, M.ApprovedOn, M.Processed, M.CancelRefId, M.Deleted)
};
This query is running OK and gives me all the data I need for the Grid.
Then for the filter I would like to add a dynamic Linq Query using the System.Linq.Dynamic.Core library
But this is as far as I get things working until now:
var outQuery = Mut.Where("Status = #0 and UserId = #1", "Nieuw", "KLM22940").Select("Status");
My questions now :
1. In the where clause If I make the fieldname variable I get an error. how to do this??
2. In the Select Clause, how to add multiple Columns? (actually I just like to output all columns.)
Best would be to see an example. has somebody used Dynamic Linq to build a dynamic linq query for the JQWidgets Grid?
Thank you very much.
In what way you are trying to use fieldname variable in where clause ?
If you want to output all columns you can use ToList()
like
var outQuery = Mut.Where("Status = #0 and UserId = #1", "Nieuw", "KLM22940").ToList();
If you want to get some specific columns you can use Select clause like this
var outQuery = Mut.Where("Status = #0 and UserId = #1", "Nieuw", "KLM22940").Select("new(Status,UserId )");
This Select clause creates data class which contains Status and UserId properties and returns a sequence of instances of that data class.

NHibernate querying with WHERE conditions in pairs

I have a collection of NHibernate objects ConcurrentBag<Event> with properties project_id and name. I want to a set of unrelated (schema wise) objects from another table which also match these properties.
The SQL I would expect would look something like:
SELECT * FROM table WHERE (project_id = 1 AND name = 'foo')
OR (project_id = 2 AND name = 'foo')
OR (project_id = 1 AND name = 'bar')
... etc
The pairs of values in the WHERE clause are based on the values from each Event in the ConcurrentBag<Event>.
I am not sure how to query this with NHibernate (ideally with LINQ). Is this even possible?
This would be difficult with LINQ I think, but if you use QueryOver it's easy to build a WHERE clause dynamically using Restrictions.Disjunction:
var disjunction = Restrictions.Disjunction();
foreach (Event evt in events)
{
disjunction.Add(Restrictions.Where<Table>(
t => t.project_id == evt.project_id && t.name == evt.name);
}
var rows = session.QueryOver<Table>()
.Where(disjunction)
.List<Table>();

LINQ Select from dynamic tableName string

I want to get list of records from an entity model (I'm using EF version 5) with a particular accountID. I'm being supplied with the tableName string (this has to be dynamic) and the accountID. I'm trying the following 2 methods but none of them is working (giving me errors on the IQueryable object 'table':
PropertyInfo info = _db.GetType().GetProperty(tableName);
IQueryable table = info.GetValue(_db, null) as IQueryable;
var query = table.Where(t => t.AccountID == accID)
.Select(t => t);
List <object> recList = ( from records in table
where records.AccountID == accID
select records).ToList<object>();
The var query = table.Where(....).Select(...) is the correct move as it allows reflection for the query builder at runtime. However, t.AccountID is an error because of the type of t remains unknown.
I've previously used a similar approach in LINQ to SQL, using System.Linq.Expressions.Expression, e.g.:
// NOT TESTED
var table=context.GetTable(dynamicTableName);
var theT=table.Experssion; // actually, I forget. DynamicExpression or MemberBinding? or
var theField=Expression.Field(theT, "AccountID"); // or dynamic name
var query=table.Where(Expression.Equal(theField, accID);
var recList=query.ToList<object>();
If your object has a common interface there is a simpler syntax:
IQueryable<MyInterface> table = context.GetTable("table") as IQueryable<MyInterface>;
var recList=from r in table
where table.AccountID == ac // if your AccountID is on MyInterface
select table;
If you only have a few tables to support, you could do this as well:
IQueryable<MyInterface> table;
if("table1"==tableName)
table=_db.table1
elseif("table2"==tableName)
table=_db.table2
elseif("table3"==tableName)
table=_db.table3
else
throw exception
I built a DynamicRepository for a project I am working on. It uses generic methods exposed through EF along with dynamic linq. It might be helpful to look at that source code here:
https://dynamicmvc.codeplex.com/SourceControl/latest#DynamicMVC/DynamicMVC/Data/DynamicRepository.cs
You can query the entity framework metadata workspace to get the type for a given table name. This link might help:
Get Tables and Relationships

LINQ queries with many-to-many tables in Entity Data Model

I'm trying to use LINQ to query the following Entity Data Model
based on this db model
I'd like to be able to pull a list of products based on ProductFacets.FacetTypeId.
Normally, I'd use joins and this wouldn't be a problem but I don't quite understand how to query many-to-many tables under the Entity DataModel.
This is an example sql query:
select p.Name, pf.FacetTypeId from Products p
inner join ProductFacets pf on p.ProductId = pf.ProductId
where pf.FacetTypeId in(8, 12)
Presuming EF 4:
var facetIds = new [] { 8, 12 };
var q = from p in Context.Products
where p.FacetTypes.Any(f => facetIds.Contains(f.FacetTypeId))
select p;
In EF (assuming the mapping is done correctly), joins are hardly ever used; navigation properties are used instead.
Your original SQL returns a tuple with repeated Name entries. With LINQ, it's often easier
to "shape" the queries into non-tuple results.
The following should be the same as the SQL, only instead of returning (Name, FacetTypeId) pairs with repeated Names, it will return a type that has a Name and a sequence of FacetTypeIds:
var facetIds = new [] { 8, 12 };
var result = from p in db.Products
select new
{
p.Name,
FacetTypeIds = from pf in p.FacetTypes
where pf.FacetTypeId == 8 || pf.FacetTypeId == 12
select pf.FacetTypeId,
};

How to write linq query based on EF?

Suppose I have three tables:
Person(pid, ...)
PersonAddress(pid, aid,...)
Address(aid, ...)
Then I want to get the person address like sql:
select a.* from address a join PersonAddress pa on a.addressID=pa.addressID
where pa.personID = myPersonID
Use Entity Framework to create Entity model, then want to write a linq equivalent as above sql.
I tried it in following way:
var addresses = this.GetAddress();
var personaddresses = this.GetPersonAddress();
var query = from ad in addresses
from pa in personaddresses
where ((ad.AddressID == pa.AddressID)&&(pa.PersonID==person.personID))
select ad;
but I got error. Or I try to start from:
var result = this.Context.Address;
var result = result.Join .... //how to write linq in this way?
How to write the linq?
This is untested but if you have all of your relationships setup and you create the model (I have used Model as the name for this) from this you should be able to use the following:
var values = this.Model.Address.Select(a => a.PersonAddress.Where(pa => pa.Id == myPersonID));
You almost never use join in LINQ to Entities.
Try:
var q = from p in Context.People
where p.PersonId == personId
from a in p.Addresses // presumes p.Addresses is 1..*
select a;
Assuming you have three entities: Person, PersonAddress and Address, here is a query that should meet your needs (this example assumes an Entity Framework context named context):
var values = context.PersonAddress.Where(pa => pa.Person.PersonId == myPersonId).Select(pa => pa.Address);
However, if the PersonAddress table exists as a pure many-to-many relationship table (i.e. contains only keys), you'd be better off setting up your Entity Framework model in such a way that the intermediate table isn't necessary, which would leave you with the much simpler:
var values = context.Person.Where(p => p.PersonId == myPersonId).Addresses;
Based on the additional feedback
Because you need to include the country table, you should originate your query from the Address table. In that case:
var values = context.Address.Where(a => a.PersonAddress.Where(pa => pa.Product.Id == myProductId).Count() > 0)
To include the Country table in the result:
var values = context.Address.Include("Country").Where(a => a.PersonAddress.Where(pa => pa.Product.Id == myProductId).Count() > 0)

Resources