SQL to LINQ with multiple joins and group by - c#

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; }
}
}

Related

SQL to Linq then to Lambda using navigation properties

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.

LINQ: Using INNER JOIN, Group and SUM and HAVING

I am trying to convert the following SQL using LINQ in c#
enter code here
SELECT t2.AccountID, t1.Name, t1.ParentID, SUM(t2.Debit), SUM(t2.Credit)
FROM t2.INNER JOIN
t1.ON t2.AccountID = t1.ID
GROUP BY t2.AccountID, t2.Name, t1.ParentID
HAVING (t1.ParentID = 22)
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication23
{
class Program
{
static void Main(string[] args)
{
Name[] names = null;
Amount[] amounts = null;
var results = (from t1 in names.Where(x => x.ParentID == 22)
join t2 in amounts on t1.ID equals t2.AccountID
select new { t1 = t1, t2 = t2 }
)
.GroupBy(x => new { accountId = x.t2.AccountID, name = x.t1.Name, parent = x.t1.ParentID })
.Select(x => new { accountID = x.Key.accountId, name = x.Key.name, parentID = x.Key.parent, debit = x.Sum(y => y.t2.Debit), credit = x.Sum(y => y.t2.Credit) })
.ToList();
}
}
public class Name
{
public int ParentID { get; set; }
public string Name { get; set; }
public int ID { get; set; }
}
public class Amount
{
public int AccountID { get; set; }
public decimal Debit { get; set; }
public decimal Credit { get; set; }
}
}

Where is the mistake? Group by, join , select .net

I donĀ“t know where is the mistake why it says that does not contain a defintion of ImporteSolicitado, interesesDemora and importeReintegro when they are colums of c and the last one of d
var importes = (from c in _context.ReintegroSolicitado
join d in _context.ReintegroRecibido on c.Expediente.ID equals d.Expediente.ID
group new {c,d} by new { c.Expediente.Codigo} into cd
select new { ImporteSolictadoFinal = cd.Sum(b => b.ImporteSolicitado + b.InteresesDemora), ImporteReintegroFinal = cd.Sum(e => e.ImporteReintegro) });
your group element contains two property c and d. So you need refer to
this property as
...
select new {
ImporteSolictadoFinal = cd.Sum(b => b.c.ImporteSolicitado + b.c.InteresesDemora),
ImporteReintegroFinal = cd.Sum(e => e.d.ImporteReintegro) }
...
This is very tough to get right with query posted. I did my best, but it is probably not exactly correct.
var importes = (from c in _context.reintegroSolicitado
join d in _context.reintegroRecibido on c.expediente.ID equals d.expediente.ID
select new { reintegroSolicitado = c, reintegroRecibido = c})
.GroupBy(x => new { c = x.reintegroSolicitado , d = x.reintegroRecibido})
.Select(cd => new { ImporteSolictadoFinal = cd.Sum(b => b.reintegroSolicitado.ImporteSolicitado + b.reintegroSolicitado.InteresesDemora), ImporteReintegroFinal = cd.Sum(e => e.reintegroRecibido.ImporteReintegro) });
}
}
public class Context
{
public List<ReintegroSolicitado> reintegroSolicitado { get; set; }
public List<ReintegroSolicitado> reintegroRecibido { get; set; }
public Expediente expediente { get; set; }
}
public class ReintegroSolicitado
{
public Expediente expediente { get; set; }
public int ImporteSolicitado { get; set; }
public int InteresesDemora { get; set; }
public int ImporteReintegro { get; set; }
}
public class Expediente
{
public int ID { get; set; }
public int Codigo { get; set; }
}

How to fill object with list using EF

How can I fill a list field using EF and linq of this model
public class Infraccion
{
public int IdInfraccion { get; set; }
public string Serie { get; set; }
public int Numero { get; set; }
public Direccion Direccion { get; set; }
public string Comentario { get; set; }
public DateTime Fecha { get; set; }
public DateTime Hora { get; set; }
public string Dominio { get; set; }
public List<Contravencion> ListaDeContravenciones = new List<Contravencion>();
}
I DO know how to fill simple propertires, but dunno how to fill field List object where Contravencion is define like
public class Contravencion
{
public string Articulo { get; set; }
public string Inciso { get; set; }
public int IdContravencion { get; set; }
public string Descripcion { get; set; }
public int UfijasMinimo { get; set; }
public int UfijasMaximo { get; set; }
}
So far this is what I have
var listadoInfracciones = (from u in _context.Usuario
join ui in _context.UsuarioInfracciones on u.UsuarioId equals ui.UserId
join i in _context.Infraccion on ui.InfraccionId equals i.InfraccionId
join d in _context.Direcciones on i.IdDireccion equals d.DireccionId
where ui.UserId == usuario.IdUsuario
select new Infraccion
{
Comentario = i.Comentario,
Direccion = new Direccion
{
Calle = d.Calle,
Entre1 = d.Interseccion1,
Entre2 = d.Interseccion2
},
Dominio = i.Dominio,
Fecha = i.Fecha,
Numero = i.Numero,
Serie = i.Serie,
ListaDeContravenciones = new List<Contravencion>()
}).ToList();
Where can't find the right way to fill the list of Contravenciones. Heres the DB model:
I've already seen these posts but do NOT fit my needs Easy way to fill object
How to get data from the database into objectlists fast (with entity framework)
Ok so i found a way to solve my problem. I'm pretty sure it's not the best way but i least have a result. If anyone can do this entirely with linq i certainly know would be helpful not just for me but for the entire comunity. Heres my code:
var listadoInfracciones = (from u in _context.Users
join ui in _context.User_Infraccion on u.UsuarioId equals ui.UserId
join i in _context.Infraccions on ui.InfraccionId equals i.InfraccionId
join d in _context.Direccions on i.IdDireccion equals d.DireccionId
where ui.UserId == usuario.IdUsuario
select new Infraccion
{
Comentario = i.Comentario,
Direccion = new Direccion
{
Calle = d.Calle,
Entre1 = d.Interseccion1,
Entre2 = d.Interseccion2
},
Dominio = i.Dominio,
Fecha = i.Fecha,
Numero = i.Numero,
Serie = i.Serie,
IdInfraccion = i.InfraccionId
}).ToList();
foreach (var inf in listadoInfracciones)
{
var test = (from contra in _context.Contravencions
where contra.Infraccion_Contravencion.Any(c => c.InfraccionId == inf.IdInfraccion)
select new Contravencion
{
Articulo = contra.Articulo,
Inciso = contra.Inciso,
UfijasMaximo = contra.UFijasMax,
UfijasMinimo = contra.UFijasMin,
Descripcion = contra.Descripcion,
IdContravencion = contra.ContravencionId
}).ToList();
inf.ListaDeContravenciones = test;
}
Cheers!

LINQ query expressions and extension methods

How to make this expression using the methods of exptension, but (!) not using anonymous types?
from p in posts
join u in context.oxite_Users on p.CreatorUserID equals u.UserID
join pa in context.oxite_PostAreaRelationships on p.PostID equals pa.PostID
join a in context.oxite_Areas on pa.AreaID equals a.AreaID
let c = getCommentsQuery(p.PostID)
let t = getTagsQuery(p.PostID)
let tb = getTrackbacksQuery(p.PostID)
let f = getFilesQuery(p.PostID)
where p.State != (byte)EntityState.Removed
orderby p.PublishedDate descending
select new Post
{ area = a, comments = c } e.t.c.
The key here is to introduce a tuple that encapsulates the combined state of the join operations and other lets. I can't repro your environment just from that, but here's a limited example that should make it clear(ish);
using System.Linq;
static class Program
{
static void Main()
{
var users = new User[0]; // intentionally 0; only exists to prove compiles
var orders = new Order[0];
var query = users.Join(orders, user => user.UserId, order => order.OrderId, (user,order) => new UserOrderTuple(user,order))
.Where(tuple => tuple.State != 42).OrderByDescending(tuple => tuple.Order.OrderId)
.Select(tuple => new ResultTuple { Comment = tuple.Comment });
}
}
class ResultTuple
{
public string Comment { get; set; }
}
class UserOrderTuple
{
public UserOrderTuple(User user, Order order)
{
User = user;
Order = order;
Comment = "some magic that gets your comment and other let";
State = 124;
}
public string Comment { get; private set; }
public int State { get; private set; }
public User User { get; private set; }
public Order Order { get; private set; }
}
class User
{
public int UserId { get; set; }
}
class Order
{
public int UserId { get; set; }
public int OrderId { get; set; }
}

Categories

Resources