C# Linq get data if exists two records - c#

I'm very bad right now in making queries but I'm trying to learn from my mistakes. I have three tables Table1, Table2 and Table3. From Table1 I want to get all the records that have in Table3 a row with Name Attribute1 and value F AND another row with Name Attribute2 and value S.
What I've tried is:
from i in entities.Table1.AsNoTracking().Where(i => (i.IsDeleted == false))
join se in entities.Table2.AsNoTracking() on i.Id equals se.SId
join set in entities.Table3.AsNoTracking().Where(i => (i.Name == "Attribute1" && i.Value.Contains("F"))
&& (i.Name == "Atrribute2" && i.Value.Contains("S")))
on i.Id equals set.SId
select new
{
Name = i.Name,
Id = i.Id
};
but it doesn't return anything. What am I doing wrong?

Try this one
from i in entities.Table1.AsNoTracking().Where(i => (i.IsDeleted == false))
join se in entities.Table2.AsNoTracking() on i.Id equals se.SId
join set in entities.Table3.AsNoTracking().Where(i => (i.Name == "Attribute1" && i.Value.Contains("F")))
on i.Id equals set.SId
join set2 in entities.Table3.AsNoTracking().Where(i => (i.Name == "Atrribute2" && i.Value.Contains("S")))
on i.Id equals set2.SId
select new
{
Name = i.Name,
Id = i.Id
};

Related

Linq SQL with Select MAX Sub Query

I have the following SQL query which has a sub query so that only the max value is in the result set:
Select
t.ID,
r.ResultIdentifier,
p.ProductID,
r.Status,
r.Start
from Result r , Transact t, Product p
WHERE r.ResultIdentifier = (Select MAX(r2.ResultIdentifier) from Result r2
where r2.Status = 'Fail'
and r2.ID = r.ID
and r2.Start >= getdate() - 30)
and r.ID = t.ID
and p.productID = 9
and t.productID = p.productID
I'm trying to convert this to a LINQ query
var failures = from result in db.Results
join transact in db.Transacts on result.ID equals transact.ID
join product in db.Products on transact.ProductID equals product.ProductID
where result.ResultIdentifier == ??
.....
select new{ ID = transact.ID,
...etc
I'm really struggling with the max ResultIdentifier in the LINQ - tried multiple variations with .MAX() but cant seem to get it right.Any suggestions welcome.
You can use the max keyword, Sorry for using method syntax as I can see you are using query :(
Should look something like the following
where result.ResultIdentifier == (Results.Max().Where(x => x.Status.equals("Fail") && x.id == result.id && x.start => Datetime.Now().Add(-30)).Select(x => x.ResultIdentifier))
Try the following query:
var results = db.Results;
var failedResults = results
.Where(r => r.Status == "Fail" && r.Start >= DataTime.Date.AddDays(-30));
var failures =
from result in results
join transact in db.Transacts on result.ID equals transact.ID
join product in db.Products on transact.ProductID equals product.ProductID
from failed in failedResults
.Where(failed => failed.ID == result.ID)
.OrderByDescending(failed => failed.ResultIdentifier)
.Take(1)
where result.ResultIdentifier == failed.ResultIdentifier
.....
select new{ ID = transact.ID,
...etc

Linq - conditional Contains()

I have the following method for filtering shops by the criteria specified in parameters:
public int[] GetShopIds(IEnumerable<Guid> OrderCreaatorIds, IEnumerable<Guid> OrderItemCategoryIds, int StatusId)
{
var query = from s in _db.Shops
join o in _db.Orders on s.Id equals o.ShopId
join oi in _db.OrderItems on o.Id equals oi.OrderId
where
OrderCreaatorIds.Contains(o.CreatorId)
&& OrderItemCategoryIds.Contains(oi.CategoryId)
&& (int)o.StatusId == StatusId
select s.Id;
return query.ToArray();
}
The thing is: OrderCreaatorIds, OrderItemCategoryIds can be null and StatusId can be 0. In that case I do not want to have those where clauses, e.g. if OrderCreaatorIds is null then the query should work as follows:
public int[] GetShopIds(IEnumerable<Guid> OrderCreaatorIds, IEnumerable<Guid> OrderItemCategoryIds, int StatusId)
{
var query = from s in _db.Shops
join o in _db.Orders on s.Id equals o.ShopId
join oi in _db.OrderItems on o.Id equals oi.OrderId
where
OrderItemCategoryIds.Contains(oi.CategoryId)
&& (int)o.StatusId == StatusId
select s.Id;
return query.ToArray();
}
etc.
Unfortunately where OrderCreaatorIds != null && OrderCreaatorIds.Contains(o.CreatorId) is not working.
public int[] GetShopIds(IEnumerable<Guid> OrderCreaatorIds, IEnumerable<Guid> OrderItemCategoryIds, int StatusId)
{
var query = from s in _db.Shops
join o in _db.Orders on s.Id equals o.ShopId
join oi in _db.OrderItems on o.Id equals oi.OrderId
select new { s = s, o = o, oi = oi };
if (null != OrderCreaatorIds)
query = query.Where(x_ => OrderCreaatorIds.Contains(x_.o.CreatorId));
if (null != OrderItemCategoryIds)
query = query.Where(x_ => OrderItemCategoryIds.Contains(x_.oi.CategoryId));
if (0 < StatusId)
query = query.Where(x_ => (int)x_.o.StatusId == StatusId);
return query.select(x_ => x_.s.Id).ToArray();
}
Maybe you will have to add some casting to IQueryable<> to make it compilable. I did not check it in compiler.
Try something like the following:
var query = from s in _db.Shops
join o in _db.Orders on s.Id equals o.ShopId
join oi in _db.OrderItems on o.Id equals oi.OrderId
where
(OrderCreaatorIds==null || OrderCreaatorIds.Contains(o.CreatorId))
&&
(OrderItemCategoryIds==null || OrderItemCategoryIds.Contains(oi.CategoryId))
&&
(StatusId==0 || (int)o.StatusId == StatusId)
select s.Id;
As you can see for each part of the where clause I have changed it from your simple predicate to an or check of two predicates. So now you have three things that are formed like A || B. Due to the way or logic works if A is true then B will be ignored. So in this case if OrderItemCategoryIds is null then it won't do the OrderItemCategoryIds.Contains check.
You can prepare the dynamic parts of the query in variables outside the query, and then use the variables inside like this:
public int[] GetShopIds(IEnumerable<Guid> OrderCreaatorIds, IEnumerable<Guid> OrderItemCategoryIds, int StatusId)
{
var orders = _db.Orders.AsQueryable();
if (StatusId != 0)
orders = orders.Where(o => o.StatusId == StatusId);
if (OrderCreaatorIds != null)
orders = orders.Where(o => OrderCreaatorIds.Contains(o.CreatorId));
var orderItems = _db.OrderItems;
if (OrderItemCategoryIds != null)
orderItems = orderItems.Where(oi => OrderItemCategoryIds.Contains(oi.CategoryId));
var query = from s in _db.Shops
join o in orders on s.Id equals o.ShopId
join oi in orderItems on o.Id equals oi.OrderId
select s.Id;
return query.ToArray();
}

How to convert SQL query to LINQ with Orderby, Groupby

I am writing to write this SQL query in linq, but didnt work..
select [ProcessTime], Count([ID]) as 'amount of processes'
from [DB].[dbo].[TableX]
where [ID] in ('ServerX', 'ServerY') and [Type] ='Complete'
group by [ProcessTime]
order by [ProcessTime]
I would like to achieve this linq & what I have tried , I split the query into two, one for process time group by clause and another to count the ID's
var query1 = (from a in this.db.Processes
where (a.ID =='ServerX' || a.ID =='ServerY') && a.Type =='Complete'
group a by a.ProcessTime into b
//here I dont know where to place orderby
select b);
var query2 = (from a in this.db.Processes
where (a.ID =='ServerX' || a.ID =='ServerY') && a.Type =='Complete'
orderby a.ProcessTime
select a).Count();
is this the right way to split the query into two and then later combine them ?
Try this:
var serverNames = new string[]{"ServerX", "ServerY"};
var result = db.Processes
.Where(p => serverNames.Contains(p.ID) && p.Type == "Complete")
.GroupBy(p => p.ProcessTime)
.Select(g => new
{
ProcessTime = g.Key,
AmountOfProcesses = g.Count()
})
.OrderBy(x => x.ProcessTime);
You can do all this in one query:
var query1 = (from a in this.db.Processes
where (a.ID == "ServerX" || a.ID == "ServerY") && a.Type == "Complete"
group a by a.ProcessTime into b
orderby b.Key
select new {ProcessTime = b.Key, Count = b.Count()});

Left Join in Entity Framework

I'm trying convert this SQL to Entity Framework LINQ, but don't working.
My SQL code:
SELECT
s.Id,
s.OriginalPhotoBlobId,
s.PhotoBlobExtension,
ISNULL(s.ProductSkuKey, p.[Key]) as [Key],
p.Name,
ISNULL(sp.Price, 0) as [Price],
sp.PriceList_Id
FROM SKUs s
INNER JOIN Products p on p.Id = s.Product_Id
LEFT JOIN SKUPrices sp on sp.SKU_Id = s.Id
My Entity Framework Code:
var db = this.Context;
var prices = from s in db.SKUs
join p in db.Products on s.Product equals p
join sp in db.SKUPrices on s equals sp.SKU into gj
from spss in gj.DefaultIfEmpty()
select new PriceListItem
{
Id = s.Id,
BlobId = s.OriginalPhotoBlobId,
BlobExtension = s.PhotoBlobExtension,
Key = ((s.ProductSkuKey == null || s.ProductSkuKey.Trim() == string.Empty) ? p.Key : s.ProductSkuKey),
Name = p.Name,
Price = (spss == null ? default(double) : spss.Price),
};
I think you should use navigation properties. Navigation properties are used to navigate through relations in data.
try joining the properties not the classes
var prices = from s in db.SKUs
join p in db.Products on s.Product_Id equals p.Id
join sp in db.SKUPrices on sp.SKU_Id = s.Id into gj
from sp in gj.DefaultIfEmpty()
select new PriceListItem
{
Id = s.Id,
BlobId = s.OriginalPhotoBlobId,
BlobExtension = s.PhotoBlobExtension,
Key = ((s.ProductSkuKey == null || s.ProductSkuKey.Trim() == string.Empty) ? p.Key : s.ProductSkuKey),
Name = p.Name,
Price = (sp == null ? default(double) : sp .Price),
};

Linq to entities query with nested query on the same table

I have a SQL query:
SELECT distinct A.stock_value_site,
A.BALANCE_QUANTITY,
A.BALANCE_NOMINAL_VALUE,
A.BALANCE_INDEXED_VALUE,
V.STOCK_VALUE_ORDER,
U.BALANCE_QUANTITY
FROM svr A,
svt V,
svu U
WHERE V.Code = 500 and
A.Id = U.ID (+) and
A.Id = (SELECT max(B.id)
FROM svr B,
sts
WHERE A.stock_value_site = B.stock_value_site and
B.Id = sts.ID(+) and
B.item = _item and
B.date < _from_date and
B.Id IS NULL)
I tried to convert this query to Linq to entities:
var data = (from A in _context.svr
join V in _context.svt on A.svtId equals V.Code
join U in _context.svu on A.Id equals U.Id into groupA
from gA in groupA.DefaultIfEmpty()
where V.Code == _openBalanceRecordId &&
A.Id == (from B in _context.svr
join st in _context.sts on B.Id equals st.Id into groupB
from gB in groupB.DefaultIfEmpty()
where A.svsId == B.svsId &&
B.ItemId == _item &&
B.Date < _startDate.Date
select B.Id).Max()
select new
{
A.stock_value_site,
A.BALANCE_QUANTITY,
A.BALANCE_NOMINAL_VALUE,
A.BALANCE_INDEXED_VALUE,
V.STOCK_VALUE_ORDER,
gA == null ? 0 : gA.BALANCE_QUANTITY
}).Distinct().ToList();
When I run the SQL query in oracle I get 33 records back. But when I run it using Linq to entities I don't get any record.
What am I doing wrong?
I believe there are still some issues with you're original query, if I understand what you're trying to do, this should work better:
var results =
(from a in _context.svr
from v in _context.svt.Where(t => t.Code == 500)
join u in _context.svu on u.Id equals a.Id into gU
from x in gU.DefaultIfEmpty()
where a.Id ==
(from b in _context.svr
join s in _context.sts on b.Id equals s.Id
where b.item = _item
and b.date < _from_date
and b.svsId == a.svsId
select b.Id).Max()
select new
{
a.stock_value_site,
a.BALANCE_QUANTITY,
a.BALANCE_NOMINAL_VALUE,
a.BALANCE_INDEXED_VALUE,
v.STOCK_VALUE_ORDER,
x == null ? 0 : x.BALANCE_QUANTITY
}).Distinct().ToList();
Or possibly this:
var results =
(from a in _context.svr
from v in _context.svt.Where(t => t.Code == 500)
join u in _context.svu on u.Id equals a.Id into gU
from x in gU.DefaultIfEmpty()
let subQuery =
(from b in _context.svr
join s in _context.sts on b.Id equals s.Id
where b.item = _item
and b.date < _from_date
select new { b.Id, b.svsId })
join y in subQuery on a.svsId equals y.svsId into gY
where a.Id = y.Max(b => b.Id)
select new
{
a.stock_value_site,
a.BALANCE_QUANTITY,
a.BALANCE_NOMINAL_VALUE,
a.BALANCE_INDEXED_VALUE,
v.STOCK_VALUE_ORDER,
x == null ? 0 : x.BALANCE_QUANTITY
}).Distinct().ToList();

Categories