I am getting runtime errors when I try and convert this stored procedure to a Linq statement about missing }.I am not sure if I am doing the CASE statement correct in linq. Is there a better way to do this?
SQL
SELECT TOP 1
C.CustomerId,
Institution = (SELECT TOP 1
CASE Name
WHEN 'In1' THEN 'Institution 1'
ELSE Name
END
FROM [Group] G
JOIN CustomerXrefs X ON X.GroupId = G.GroupId AND G.GroupTypeId = 308
WHERE X.CustomerId = C.CustomerId),
G.GroupId
FROM
Customer C
JOIN
CustomerXrefs X ON C.CustomerId = X.CustomerId
JOIN
[Group] G ON X.GroupId = G.GroupId
WHERE
C.Email = #Email
AND G.GroupTypeId = 308
ORDER BY
G.GroupId
Linq
var query1 =
(from c in db.Customers
join cx in db.CustomerXrefs on c.CustomerId equals cx.CustomerId
join g in db.Groups on cx.GroupId equals g.GroupId
select new Customer
{
CustomerId = c.CustomerId,
Institution = (from ig in db.Groups
join icx in db.CustomerXrefs
on ig.GroupId equals icx.GroupId && ig.GroupTypeId == 308
where icx.CustomerId == c.CustomerId
select new Institution
{
Name = ig.Name == "In1 " ? "Institution 1" :
ig.Name == "In2" ? "Institution 2" :
ig.Name
}).FirstOrDefault();
}).FirstOrDefault();
I got rid of all errors by simulating with classes
class Program
{
static void Main(string[] args)
{
DataBase db = new DataBase();
var query1 = (from c in db.Customers
join cx in db.CustomerXrefs on c.CustomerId equals cx.CustomerId
join g in db.Groups on cx.GroupId equals g.GroupId
select new Customer
{
CustomerId = c.CustomerId,
Institution = (from ig in db.Groups
join icx in db.CustomerXrefs on ig.GroupId equals icx.GroupId
where icx.CustomerId == c.CustomerId && ig.GroupTypeId == 308
select new Institution()
{
Name = ig.Name == "In1 " ? "Institution 1" :
ig.Name == "In2" ? "Institution 2" :
ig.Name
}
).FirstOrDefault()
});
}
}
public class DataBase
{
public List<Customer> Customers { get; set; }
public List<CustomerXrefs> CustomerXrefs { get; set; }
public List<Group> Groups { get; set; }
}
public class Customer
{
public string CustomerId { get; set; }
public Institution Institution { get; set; }
}
public class CustomerXrefs
{
public string CustomerId { get; set; }
public string GroupId { get; set; }
}
public class Group
{
public string GroupId { get; set; }
public int GroupTypeId { get; set; }
public string Name { get; set; }
}
public class Institution
{
public string Name { get; set; }
}
Related
I'm trying to build a lambda expression to get the grand total but I'm still struggling to achieve the desired result. I've managed to achieve the same using SQL and LINQ using joints but it would be great if someone could give me a hand to re-write the query using lambda and navigation properties (without joints).
SQL Query:
SELECT SUM(a.[Quantity] * (a.[Price] + b.[ExtraValue])) + SUM(d.SubMealTotal * a.[Quantity]) AS [Total]
FROM [dbo].[OrderedMeals] a
INNER JOIN [dbo].[OrderedMealPortions] b
ON a.Id = b.[OrderedMealId]
LEFT OUTER JOIN (SELECT OrderedMealId, Sum(Price) AS SubMealTotal FROM [dbo].[OrderedSubMeals]
GROUP BY OrderedMealId) AS d
ON a.Id = d.[OrderedMealId]
WHERE a.[Quantity] > 0
Then the LINQ - Please let me know if I'm missing something here or there is a better way:
(from orderedMeal in _context.OrderedMeals.Where(x => x.Quantity > 0)
join orderedMealPortion in _context.OrderedMealPortions
on orderedMeal.Id equals orderedMealPortion.OrderedMealId
join orderedSubMeal in _context.OrderedSubMeals
on orderedMeal.Id equals orderedSubMeal.OrderedMealId into gs
from subOrderedSubMeal in gs.DefaultIfEmpty()
group subOrderedSubMeal by new { subOrderedSubMeal.OrderedMealId, orderedMeal.Price, orderedMeal.Quantity, orderedMealPortion.ExtraValue } into g
select new
{
MealTotal = (g.Key.ExtraValue + g.Key.Price) * g.Key.Quantity + g.Sum(x => x.Price * g.Key.Quantity),
}).Sum(x => x.MealTotal); // Not sure how to get the sum using LINQ
Entities:
public class OrderedMeal
{
public int Id { get; set; }
public int Quantity { get; set; }
public decimal Price { get; set; }
public int OrderedMealPortionId { get; set; }
public OrderedMealPortion? OrderedMealPortion { get; set; }
public ICollection<OrderedSubMeal>? OrderedSubMeals { get; set; }
}
public class OrderedMealPortion
{
public int Id { get; set; }
public int OrderedMealId { get; set; }
public OrderedMeal? OrderedMeal { get; set; }
public decimal? ExtraValue { get; set; }
}
public class OrderedSubMeal
{
public int Id { get; set; }
public int OrderedMealId { get; set; }
public OrderedMeal? OrderedMeal { get; set; }
public decimal Price { get; set; }
}
I can't test with a database, but I think this implements the query logic and will produce the same result:
var ans = OrderedMeals
.Where(om => om.Quantity > 0 && om.OrderedMealPortion != null)
.Sum(om => om.Quantity * (om.Price +
om.OrderedMealPortion!.ExtraValue +
(om.OrderedSubMeals != null ? om.OrderedSubMeals.Sum(osm => osm.Price) : 0)) );
This is direct translation from the SQL:
var groupingQuery =
from sm in _context.OrderedSubMeals
group sm by new { sm.OrderedMealId } into g
select new
{
g.Key.OrderedMealId,
SubMealTotal = g.Sum(x => x.Price)
};
var query =
from om in _context.OrderedMeals
join g in groupingQuery on om.Id equals g.OrderedMealId into gj
from g in gj.DefaultIfEmpty()
where om.Quantity > 0
select new { om, om.OrderedMealPortion, g };
var result = query.Sum(x => x.om.Quantity * (x.om.Price + x.OrderedMealPortion.ExtraValue + x.g.SubMealTotal));
But I have feeling that query can be simplified without grouping.
I need to translate the following SQLite query to LINQ in C#
SELECT sup.SupplierName, sup.SupplierID, pr.Price, max(pr.AddedDate)
FROM Suppliers sup
LEFT JOIN ItemsPrices pr
USING(SupplierID)
WHERE pr.ItemID = '22'
GROUP BY sup.SupplierName
I've searched about all web site and tried the following LINQ query and it does group like what I want but doesn't select latest date. I'm newbie in LINQ please help me
internal List<LatestPriceDbo> GetLatestPrice(int _itemid)
{
using (dbContext context = new dbContext())
{
var groupedPrice = from a in context.ItemsPrices
where a.ItemId == _itemid
orderby a.Id descending
group a by new { a.ItemId, a.SupplierId } into g
select new ItemsPrice
{
SupplierId = g.Key.SupplierId,
ItemId = g.Key.ItemId,
Price = g.FirstOrDefault().Price,
AddedDate = g.Max(s => s.AddedDate)
};
var result = (from c in context.Suppliers
from k in groupedPrice
where k.ItemId == _itemid && c.SupplierId == k.SupplierId
select new LatestPriceDbo
{
supid = c.SupplierId,
supname = c.SupplierName,
price = k.Price,
addeddate = k.AddedDate
}).ToList();
return result;
}
}
internal class LatestPriceDbo
{
public int supid { get; set; }
public string supname { get; set; }
public decimal price { get; set; }
public string addeddate { get; set; }
}
I am using Database-First.
You should be able to use a LINQ Join I have mocked up something which might point you in the correct direction:
Notes
use the join first to get the set you looking for
you can then do a nested select for the max based on supplierId.
from a in context.ItemsPrices
join s in context.Suppliers on a.SupplierId equals s.supplierId
where a.ItemId == _itemid
orderby a.Id descending
select new ItemsPrice
{
SupplierName = s.SupplierName
SupplierId = a.SupplierId,
ItemId = a.ItemId,
Price = a.FirstOrDefault().Price,
AddedDate = context.ItemsPrices.Where(x => x.SupplierId == a.SupplierId).Max(s => s.AddedDate)
};
I solved the problem owing to Kevin's suggestion. I did need to be more search on web to improve the code block of Kevin's comment and I did.
internal List<LatestPriceDbo> GetLatestPrice(int _itemid)
{
using (dbContext context = new dbContext())
{
var result = (from a in context.ItemsPrices
join s in context.Suppliers on a.SupplierId equals s.SupplierId
where a.ItemId == _itemid
orderby a.Id descending
group new { a, s } by new { a.SupplierId, a.ItemId } into grb
select new LatestPriceDbo
{
supname = grb.FirstOrDefault().s.SupplierName,
supid = grb.Key.SupplierId,
itemid = grb.Key.ItemId,
price = context.ItemsPrices
.Where(x => x.ItemId == grb.FirstOrDefault().a.ItemId)
.OrderByDescending(z => z.Id).Select(z => z.Price)
.FirstOrDefault(),
addeddate = context.ItemsPrices
.Where(x => x.SupplierId == grb.FirstOrDefault().a.SupplierId)
.Max(s => s.AddedDate)
}).ToList();
return result;
}
}
internal class LatestPriceDbo
{
public int itemid { get; set; }
public int supid { get; set; }
public string supname { get; set; }
public decimal price { get; set; }
public string addeddate { get; set; }
public int recordid { get; set; }
}
I am working to convert the below SQL code to LINQ query for MVC. It got multiple nested joins and group by.
SELECT UnitTracts.Id,
UnitTracts.UnitId,
Leases.Id,
Leases.Lessor,
Leases.Lessee,
Leases.Alias,
Leases.LeaseDate,
Leases.GrossAcres,
IIf([Page] Is Null,[VolumeDocumentNumber],[VolumeDocumentNumber] + '/' + [Page]) AS [Vol/Pg],
Leases.Legal,
Interests.TractId,
Leases.NetAcres,
UnitTracts.AcInUnit
FROM (UnitTracts INNER JOIN (((WorkingInterestGroups INNER JOIN Interests ON WorkingInterestGroups.Id = Interests.WorkingInterestGroupId)
INNER JOIN Tracts ON Interests.TractId = Tracts.Id)
INNER JOIN Leases ON WorkingInterestGroups.LeaseId = Leases.Id)
ON UnitTracts.TractId = Tracts.Id)
LEFT JOIN AdditionalLeaseInfo ON Leases.Id = AdditionalLeaseInfo.LeaseId
where unitId = 21
GROUP BY UnitTracts.Id,
UnitTracts.UnitId,
Leases.Id,
Leases.Lessor,
Leases.Lessee,
Leases.Alias,
Leases.LeaseDate,
Leases.GrossAcres,
IIf([Page] Is Null,[VolumeDocumentNumber],[VolumeDocumentNumber] + '/' + [Page]),
Leases.Legal,
Interests.TractId,
Leases.NetAcres,
UnitTracts.AcInUnit
This the query I got but it returns less records. I tried to convert from SQL to LINQ but it did not work. I really stuck now.
var leases = (from l in db.Leases
where l.Active
join ali in db.AdditionalLeaseInfoes on l.Id equals ali.LeaseId
where ali.Active
join wig in db.WorkingInterestGroups on l.Id equals wig.LeaseId
where wig.Active
join interest in db.Interests on wig.Id equals interest.WorkingInterestGroupId
where interest.Active
join tr in db.Tracts on interest.TractId equals tr.Id
where tr.Active
join ut in db.UnitTracts on tr.Id equals ut.TractId
where ut.Active
group new { l, wig, interest, tr, ali, ut } by
new
{
Id = ut.Id,
UnitId = ut.UnitId,
LeaseId = l.Id,
Lessor = l.Lessor,
Lessee = l.Lessee,
Alias = l.Alias,
LeaseDate = l.LeaseDate,
GrossAcres = l.GrossAcres,
VolPg = l.Page == null ? l.VolumeDocumentNumber : l.VolumeDocumentNumber + "/" + l.Page,
Legal = l.Legal,
TractId = interest.TractId,
NetAcres = l.NetAcres,
AcInUnit = ut.AcInUnit
} into lease
select new LeasesViewModel
{
UnitId = lease.Key.UnitId,
TractId = lease.Key.TractId,
LeaseId = lease.Key.LeaseId,
LeaseAlias = lease.Key.Alias,
Pooling = lease.Where(x => x.l.Id == lease.Key.LeaseId).Select(x => x.l.NoPooling).FirstOrDefault() ? "No" :
lease.Where(x => x.l.Id == lease.Key.LeaseId).Select(x => x.l.Pooling).FirstOrDefault() ? "Yes" : "No Review",
Lessor = lease.Key.Lessor,
GrossAc = lease.Key.GrossAcres
}).Where(x => x.UnitId == unitId).OrderBy(x => x.TractId).ToList();
Thanks for help!!
Thanks for help!!
Thanks for help!!
Thanks for help!!
I modeled you query with classes to get syntax correct :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
List<WorkingInterestGroups> workingInterestGroups = new List<WorkingInterestGroups>();
List<UnitTracts> unitTracts = new List<UnitTracts>();
List<Tracts> tracts = new List<Tracts>();
List<Leases> leases = new List<Leases>();
List<AdditionalLeaseInfo> additionalLeaseInfos = new List<AdditionalLeaseInfo>();
List<Interests> interests = new List<Interests>();
var results = (from unitTract in unitTracts
join tract in tracts on unitTract.TractId equals tract.Id
join interest in interests on tract.Id equals interest.TractId
join workingInterestGroup in workingInterestGroups on interest.WorkingInterestGroupId equals workingInterestGroup.Id
join lease in leases on workingInterestGroup.LeaseId equals lease.Id
join additionalLeaseInfo in additionalLeaseInfos on lease.Id equals additionalLeaseInfo.LeaseId
where unitTract.UnitId == "21"
select new { unitTract = unitTract, tract = tract, interest = interest, workingInterestGroup = workingInterestGroup,
lease = lease, additionalLeaseInfo = additionalLeaseInfo}).ToList();
var groups = results.GroupBy(x => new
{
x.unitTract.Id,
x.unitTract.UnitId,
x.lease.Lessor,
x.lease.Lessee,
x.lease.Alias,
x.lease.LeaseDate,
x.lease.GrossAcres,
x.lease.Legal,
x.interest.TractId,
x.lease.NetAcres,
x.unitTract.AcInUnit
})
.ToList();
}
}
public class WorkingInterestGroups
{
public string Id { get; set; }
public string LeaseId { get; set; }
}
public class UnitTracts
{
public string TractId { get; set; }
public string Id { get; set; }
public string UnitId { get; set; }
public string AcInUnit { get;set;}
}
public class Tracts
{
public string Id { get; set; }
}
public class Leases
{
public string Id { get; set; }
public string Lessor { get; set; }
public string Lessee { get; set; }
public string Alias { get; set; }
public string LeaseDate { get; set; }
public string GrossAcres { get; set; }
public string Legal { get; set; }
public string NetAcres { get; set; }
}
public class AdditionalLeaseInfo
{
public string LeaseId { get; set;}
}
public class Interests
{
public string TractId { get; set; }
public string WorkingInterestGroupId { get; set; }
}
}
I need a little help in converting SQL to Linq. It's pretty straight forward in MySQL...
Table: customers
ID Name
1 Bill
2 John
Table: purchases
ID CustomerID CompletedTransaction
1 1 False
2 2 True
3 1 True
4 1 True
SELECT c.ID
c.Name,
COUNT(p.ID) AS TotalPurchases,
SUM(CASE WHEN p.CompletedTransaction = TRUE THEN 1 ELSE 0 END) AS TotalCompleted
FROM customers c
LEFT JOIN purchases p ON c.ID = p.CustomerID
GROUP BY c.ID
Expected Result:
1, Bill, 3, 2
2, John, 1, 1
I've seen a few examples on how to implement a left join in Linq but I'm not sure how to include a SUM and Count into this. I've seen examples in Linq where the fields returned are selected from the group keys. Does this mean that if I have more fields in the customers table such as address and other contact details which I'd like to return, I'd have to include them in the join to then be able to select them? Hope this makes sense. Appreciate any help or links that might point me in the right direction.
Thanks
var answer = (from c in db.customers
join p in db.purchases
on c.ID = p.CustomerID into subs
from sub in subs.DefaultIfEmpty()
group sub by new { c.ID, c.Name } into gr
select new {
gr.Key.ID,
gr.Key.Name,
Total = gr.Count(x => x != null),
CountCompleted = gr.Count(x => x != null && x.CompletedTransaction)
}).ToList();
Here's the sample
class Program
{
static void Main(string[] args)
{
List<Customers> customers = new List<Customers>();
customers.Add(new Customers() { ID = 1, Name = "Bill" });
customers.Add(new Customers() { ID = 2, Name = "John" });
List<Purchases> purchases = new List<Purchases>();
purchases.Add(new Purchases() { ID = 1, CustomerID = 1, CompletedTransaction = false });
purchases.Add(new Purchases() { ID = 2, CustomerID = 2, CompletedTransaction = true });
purchases.Add(new Purchases() { ID = 3, CustomerID = 1, CompletedTransaction = true });
purchases.Add(new Purchases() { ID = 4, CustomerID = 1, CompletedTransaction = true });
IEnumerable<JoinResult> results = from c in customers
join p in purchases
on c.ID equals p.CustomerID
group new { c, p } by new {p.CustomerID, c.Name} into r
select new JoinResult
{
CustomerID = r.Key.CustomerID,
CustomerName = r.Key.Name,
TotalPurchases = r.Count(),
TotalCompleteTransaction = r.Where(s=> s.p.CompletedTransaction).Count()
};
foreach(JoinResult r in results)
{
Console.WriteLine($"CustomerID : {r.CustomerID} | Name : {r.CustomerName} | TotalPurchases : {r.TotalPurchases} | TotalCompleteTransaction : {r.TotalCompleteTransaction}");
}
Console.ReadKey();
}
}
class Customers
{
public int ID { get; set; }
public string Name { get; set; }
}
class Purchases
{
public int ID { get; set; }
public int CustomerID { get; set; }
public bool CompletedTransaction { get; set; }
}
class JoinResult
{
public int CustomerID { get; set; }
public string CustomerName { get; set; }
public int TotalPurchases { get; set; }
public int TotalCompleteTransaction { get; set; }
}
Result
I have 3 tables:
tblCompany : Id, Name, Location
tblRating : Id, CompanyId, Rate
tblImages : Id, CompanyId, ImagePath
I have a class
public class Company
{
public string Id { get; set; }
public string CompanyName { get; set; }
public string Location { get; set; }
public string AverageRate { get; set; }
public List<string> ImagePath { get; set; }
}
I want a LINQ query to produce a result to match the Company class.
I wrote this query but it does not work
List<Company> result = null;
using (DataContext dc = new DataContext())
{
result = (from a in dc.GetTable<tblCompany>()
join b in dc.GetTable<tblRating>()
on a.Id equals b.CompanyId
join c in dc.GetTable<tblImages>()
on a.Id equals c.CompanyId
select new SearchResult
{
CompanyName = a.Company,
Location = a.Location,
AverageRate = b.Rate.Average(),
ImagePath = c.ImagePath.ToList()
}).ToList<Company>();
}
Edited for whole Query:
(I've to say i'm sorry but i have no way of testing this query yet)
You can use the let clause instead of the joins:
var result = (from c in dc.GetTable<tblCompany>()
let r = (from re in dc.GetTable<tblRating>()
where re.CompanyId == c.Id && re.Rate != null
select re.Rate)
let i = (from im in dc.GetTable<tblImages>()
where im.CompanyId == c.Id
select im.ImagePath)
select new SearchResult
{
CompanyName = c.Name,
Location = c.Location,
AverageRate = r.Average(),
ImagePath = i.ToList()
}).ToList<Company>();
try this -
result = (from a in dc.GetTable<tblCompany>()
join b in dc.GetTable<tblRating>()
on a.Id equals b.CompanyId
join c in dc.GetTable<tblImages>()
on a.Id equals c.CompanyId
group new { b.Rate, c.ImagePath}
by new { a.Id, a.Location,a.Name} into groupList
select new Company
{
CompanyName = groupList.Key.Name,
Location = groupList.Key.Location,
AverageRate = groupList.Average(a=>a.Rate),
ImagePath = groupList.Select(i=>i.ImagePath).ToList()
}).ToList<Company>();