Linq several relations - linq

I can't make it works.... I've got 4 tables:
T1 (1)---(N) T2 (N)---(1) T3 (1)--(N) T4
So, from T1 how can I get T4 data being T1 an IQueryable that I get from previous select?
I tried T1.T2.Where(x=>...Select(y=>..)) cause I think select is for this case because T3's relations but I doesn't compile...
I've got it working with no previous IQueryable statement, using inner joins, but because other things I need it to work that way.

private void getT4s()
{
var t1 = new T1();
var t4s = t1.T2s.Select(x => x.T3).SelectMany(x => x.T4s);
}
public class T1
{
public ICollection<T2> T2s { get; set; }
}
public class T2
{
public T3 T3 { get; set; }
}
public class T3
{
public ICollection<T2> T4s { get; set; }
}
public class T4
{
}

Related

PredicateBuilder with navigation properties and multiple conditions

I'm using the PredicateBuilder in the LinqKit to dynamically form the Where expression. When either LastName or FirstName from the SearchCriteria is populated then the SQL statement works correctly. However when both FirstName and LastName are used to search for ConsumerAccount then the generated SQL (as shown below) will not bring back the correct number of rows.
SELECT distinct [c].[consumerAccountId]
FROM [dbo].[ConsumerAccount] AS [c]
INNER JOIN [ConsumerAccountOwner] AS [c4] on [c].[ConsumerAccountId] = [c4].[ConsumerAccountId]
INNER JOIN [Consumer] AS [c5] ON [c4].[ConsumerId] = [c5].[ConsumerId]
WHERE EXISTS (
SELECT 1
FROM [consumeraccountowner] AS [c0]
INNER JOIN [consumer] AS [c1] ON [c0].[consumerId] = [c1].[consumerId]
WHERE [c].[consumerAccountId] = [c0].[consumerAccountId] AND [c1].[FirstName]) = 'fName') AND EXISTS (
SELECT 1
FROM [ConsumerAccountOwner] AS [c2]
INNER JOIN [Consumer] AS [c3] ON [c2].[ConsumerId] = [c3].[ConsumerId]
WHERE [c].[ConsumerAccountId] = [c2].[ConsumerAccountId] AND [c3].[LastName]) = 'lName')
Is there a way to get it to generate the WHERE clause with both conditions for LastName and FirstName as follows?
WHERE EXISTS (
SELECT 1
FROM [consumeraccountowner] AS [c0]
INNER JOIN [consumer] AS [c1] ON [c0].[consumerId] = [c1].[consumerId]
WHERE [c].[consumerAccountId] = [c0].[consumerAccountId] AND [c1].[FirstName]) = 'fName' AND [c1].[LastName]) = 'lName')
public static void Main()
{
var searchCriteria = new SearchCriteria();
searchCriteria.SearchLastName = "LastName1";
searchCriteria.SearchFirstName = "FirstName1";
var predicate = PredicateBuilder.New<ConsumerAccount>();
if (!string.IsNullOrEmpty(searchCriteria.SearchLastName))
{
predicate = predicate.And(ca => ca.Owners.Any(o => o.Consumer.LastName.Equals(searchCriteria.SearchLastName)));
}
if (!string.IsNullOrEmpty(searchCriteria.SearchFirstName))
{
predicate = predicate.And(ca => ca.Owners.Any(o => o.Consumer.FirstName.Equals(searchCriteria.SearchFirstName)));
}
var query = (from ca in _dbContext.ConsumerAccounts.AsExpendable().Where(predicate)
join ao in _dbContext.AccountOwners on ca.Id equals ao.Id
join c in _dbContext.Consumers on ao.ConsumerId equals c.ConsumerId
select ca.Id).Distinct();
var accountCount = query.Count();
}
public class SearchCriteria
{
public string SearchLastName { get; set; }
public string SearchFirstName { get; set; }
}
public class Consumer
{
public int Id { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public List<ConsumerAccount> Accounts { get; set; }
}
public class ConsumerAccount
{
public int Id { get; set; }
public int ConsumerId { get; set; }
public List<AccountOwner> Owners { get; set; }
}
public class AccountOwner
{
public int Id { get; set; }
public int ConsumerId { get; set; }
public int ConsumerAccountId { get; set; }
public Consumer Consumer { get; set; }
}
I have tried to join the tables in different ways but could not to get it to work for all scenarios.
You need an if statement for the case when both inputs are non-empty, and then move the conjunction into the any, so that both conditions are for the same person:
if (!string.IsNullOrEmpty(searchCriteria.SearchLastName) && !string.IsNullOrEmpty(searchCriteris.SearchFirstName))
{
predicate = predicate.And(ca => ca.Owners.Any(o => o.Consumer.LastName.Equals(searchCriteria.SearchLastName)) && o.Consumer.FirstName.Equals(searchCriteria.SearchFirstName)));
}
If you need a large amount of conditions filtering on different parts of the entity graph, you probably want to build multiple dynamic predicates for each subgraph filter. E.g the owner filters should go in an owner specific predicate, so that they all apply to one owner, and any filters on the account should be added to a separate predicate.

How to select a nested object with EF Core and Linq?

Hope someone can help me
I've some tables linked Table1-->Table2-->Table3-->Table4
The relationship is one to many (a record of Table1 has many records of Table2, each one of them has many records of Table3.......).
I have an Id of the Table1 and I need to get the data set of any property of Table4 (only these data). I can use Include and ThenInclude in LINQ to reach the last table, but... how could I select only these data?
I've a code like this one:
_databaseContext.Table1.Where(t1 => t1.Id == id)
.Include(t1 => t1.Table2Nav)
.ThenInclude(t2 => t2.Table3Nav)
.ThenInclude(t3 => t3.Table4Nav)
.ToList();
This returns to me the complete structure from the first table, but, how could I do a select of specific properties of Table4 (let's suposse that Table4 has a property named "Result" and I need recover a list of all values of "Result" I can reach from the Id of Table1.
Thank's in advance
UPDATE: Here's an example of the structure of the classes:
public class Table1
{
public int Id { get; set; }
public List<Tables12> Tables12Nav { get; set; }
}
public class Tables12
{
public int Id { get; set; }
public Table1 Table1Nav { get; set; }
public Table2 Table2Nav { get; set; }
}
public class Table2
{
public int Id { get; set; }
public List<Tables12> Tables12Nav { get; set; }
public List<Table3> Table3Nav { get; set; }
}
public class Table3
{
public int Id { get; set; }
public Table2 Table2Nav { get; set; }
public List<Table4> Table4Nav { get; set; }
}
public class Table4
{
public int Id { get; set; }
public Table3 Table3Nav { get; set; }
public string Result { get; set; }
}
You could use link to sql to get your data :
var TableD = from a in db.TableA
join b in db.TableB on a.Id equals b.TableAId
join c in db.TableC on b.Id equals c.TableBId
join d in db.TableD on c.Id equals d.TableCId
where a.Id == 2
select d;
if you'd like use your code you can retrieve table 4 (table d) as :
var TableD = TableTemp.SelectMany(a => a.TableB.SelectMany(
b => b.TableC.SelectMany(
c => c.TableD
)));

LINQ: How to filter collection by data in related table

I have two Entity Framework Core entities:
public class JobOrder {
public int Id { get; set; }
public string JobTitle { get; set; }
public string Status { get; set; }
...
public IEnumerable<JobOrderUser> JobOrderUsers { get; set; }
}
public class JobOrderUser {
public int AppUserId { get; set; }
public AppUser User { get; set; }
public int JobOrderId { get; set; }
public JobOrder JobOrder { get; set; }
}
The second one is a join table used for a many-to-many between the JobOrder and User tables but I don't need to drill to the User table for this.
I want to get a collection of JobOrders that have an association with a specific user. In SQL, I would write something like this:
select distinct
a.*
from
JobOrders a
join JobOrderUser b on a.JobOrderID = b.JobOrderId
where
b.AppUserId = someId
How do I do that using LINQ method syntax?
If your entities are set up correctly, and their relationships are intact, you could load the JobOrderUsers while querying for a JobOrder and then filter by a user. Something like
JobOrder.Include(t => t.JobOrderUsers).Where(t => t.JobOrderUsers.Any(x => x.User.Id == SomeId));
You can also use the below query using join and Select the required columns data in a jobOrdersDto class. For that, you have to inject the _jobOrdersRepository and _jobOrderUserRepository repositories to your service where you are calling the required method.
var result = (from jobOrders in _jobOrdersRepository.GetAll()
join jobOrderUser in _jobOrderUserRepository.GetAll() on jobOrders.JobOrderID equals jobOrderUser.JobOrderId
where
(jobOrderUser.AppUserId == someId)
select new jobOrdersDto
{
}
Your Service class:
public class YourService
{
private readonly IRepository<jobOrders> _jobOrdersRepository;
private readonly IRepository<jobOrderUser> _jobOrderUserRepository;
public YourService(
IRepository<jobOrders> jobOrdersRepository, IRepository<jobOrderUser> jobOrderUserRepository)
: base()
{
_jobOrdersRepository = jobOrdersRepository;
_jobOrderUserRepository = jobOrderUserRepository;
}
}

How to write the following in LINQ syntax?

Just wondering how to write the following SQL in LINQ syntax
select * from COESDetails
where COESNo in
(select distinct COESNo from COESDefects)
either Fluent or Query Expression, or Both
COESDefects have a navigation property to COESDetails
public class COESDefects
{
public int Id { get; set; }
public int COESNo { get; set; }
public string Comments { get; set; }
public virtual COESDetails COESDetails { get; set; }
}
public class COESDetails
{
public COESDetails()
{
COESDetailsCOESDefects = new List<COESDefects>();
}
public int COESNo { get; set; }
public int Postcode { get; set; }
public virtual ICollection<COESDefects> COESDetailsCOESDefects { get; set; }
}
Thanks
Try this:
var query =
from x in context.COESDetails
join y in context.COESDefects on x.COESNo equals y.COESNo into ys
where ys.Any()
select x;
I feel like it would be as simple as this:
yourDbContext.COESDetails.Where(detail => detail.COESDetailsCOESDefects.Any()).ToList();
Correct me if I'm wrong.
Sometimes, if the query is complex, it's easier to just execute it directly e.g.
IEnumerable<COESDetails> myResults = dbConext.ExecuteQuery<CCOESDetails>("select * from COESDetails where COESNo in (select distinct COESNo from COESDefects)")

How to use LINQ to retrieve child collection

Starting here:
public class Customer
{
public int CustomerID { get; set; }
public string CustomerName { get; set; }
public IList<Order> Orders { get; set; }
}
public class Order
{
public int OrderID { get; set; }
public int CustomerID { get; set; }
}
What would be the linq query that you write to retrieve all Orders from all Customers?
Something to the effect of:
IList<Order> orders = new List<Order>();
foreach (Customer c in Customers)
{
orders.Union(c.Orders);
}
I tried the following but it throws an "nhibernate collection was not an association" exception:
var orders = from c in Customers
select c.Orders;
I know I'm missing something, but I can't find a way to achieve this in linq.
var orders = from c in db.Customers
from o in c.Orders
select o;
Or
var orders = db.Customers.SelectMany(c => c.Orders);
Will it work in linq for nhibernate? I don't know.
Make sure your foreign key constraint is setup properly from [Order].[CustomerID] to [Customer].[ID] in the database.

Resources