Join two tables using entity framework and linq in c# - c#

I am trying to combine two tables in c# for orderManagement.where "SalesOrderDetails" table returns query results 1 comma seperated product code and quantity
query results 2
"SalesOrder" table return order detail.
I have Written stored procedure
ALTER procedure [dbo].[SP_GetAllOrders]
AS
BEGIN
SELECT
SalesOrder.OrderDate,
SalesOrder.OrderTitle,
SalesOrder.OrderPriority,
Customer.Lname,
Customer.Fname,
OrderType.OrderTypeName,
(
SELECT
CAST( ProductCode AS varchar ) + ':' + CAST( Quantity AS varchar ) + ','
FROM
SalesOrderDetails
WHERE
SalesOrderDetails.SalesOrderId = SalesOrder.SalesOrderId
FOR xml path('')
) AS 'Product'
FROM
SalesOrder
INNER JOIN Customer ON SalesOrder.CustomerId = Customer.CustomerId
INNER JOIN OrderType ON SalesOrder.OrderTypeId = OrderType.OrderTypeId
END
It gives me perfect output.same output I want without using stored procedure.
I want same output using entity framework,linq and c# asp.net.I am stuck here
this is what i have tried
TrainingDemoEntities entity = new TrainingDemoEntities();
var details = (from order in entity.SalesOrders
join cust in entity.Customers
on order.CustomerId equals cust.CustomerId
join ordertypevalue in entity.OrderTypes
on order.OrderTypeId equals ordertypevalue.OrderTypeId
select new
{
orderId = order.SalesOrderId,
orderDate = order.OrderDate,
orderTitle = order.OrderTitle,
orderPriority = order.OrderPriority,
orderType = order.OrderType,
productstr = string.Join(",", (from prod in entity.SalesOrderDetails
where prod.SalesOrderId == order.SalesOrderId
select prod.ProductCode + ":" + prod.Quantity))
}).ToList();

Related

Generic model to call a stored procedure .net core

ALTER PROCEDURE [dbo].[ListaUnidadAlumnos]
#MateriaId INT,
#UnidadId INT,
#Columnas AS NVARCHAR(MAX) = Null,
#Query AS NVARCHAR(MAX) = Null
AS
BEGIN
SET NOCOUNT ON;
SELECT
#Columnas = STUFF((SELECT ',' + QUOTENAME(convert(char(10), L.Fecha, 120))
FROM (SELECT DISTINCT(A.Fecha)
FROM Asistencias A
INNER JOIN AspNetUsers U ON A.AlumnoId = U.Id
INNER JOIN Unidades UN ON UN.UnidadId = A.UnidadId
INNER JOIN Materias M ON UN.MateriaId = M.MateriaId
WHERE UN.MateriaId = #MateriaId
AND UN.UnidadId = #UnidadId) L
GROUP BY L.Fecha
ORDER BY L.Fecha asc
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
SET #Query = 'SELECT AlumnoId, ' + #Columnas + ' from
(
SELECT A.AlumnoId, A.Fecha, A.Valor
FROM Asistencias A
INNER JOIN AspNetUsers U ON A.AlumnoId = U.Id
) x
pivot
(
max(Valor)
for Fecha in (' + #Columnas + ')
) p '
EXECUTE(#query)
This stored procedure returns:
The dates are dynamic, depending on the assistance of the class
I am not using entity framework, I execute the procedures in the following way
public async Task ObtenerListaMateria(int materiaId)
{
var pMateriaId = new SqlParameter("#MateriaId", materiaId);
ListaAlumnosIdMateria = await _context.ListaAlumnosIdMateria
.FromSql("EXEC ObtenerListaAlumnosIdMateria #MateriaId", pMateriaId)
.ToListAsync();
ViewData["NumeroAlumnos"] = ListaAlumnosIdMateria.Count();
ViewData["Contador"] = 0;
}
If I execute the procedures in this way, first I have to create the model with the data that they see in the procedure
My question is, how do you call the procedure if the query will always give me a different number of dates, can I create a generic model?

Select records count from multiple tables in a single query

I have some models (restaurants, shops, products), and i want to select records count for multiple models in a single linq query.
I know how it should be in sql, but i don't know how to translate it in linq:
select
(select count(*) from restaurants) as restaurantsCount,
(select count(*) from shops) as shopsCount,
(select count(*) from products) as productsCount
from
dual
Considering dual is a dummy table with single row:
var result = new
{
RestaurantsCount = context.Restaurants.Count(),
ShopsCount = context.Shops.Count(),
ProductsCount = context.Products.Count()
};
Single query solution:
var result = from dummyRow in new List<string> { "X" }
join product in context.products on 1 equals 1 into pg
join shop in context.shops on 1 equals 1 into sg
join restaurant in context.restaurants on 1 equals 1 into rg
select new
{
productsCount = pg.Count(),
shopsCount = sg.Count(),
restaurantsCount = rg.Count()
};

How can we create a dynamic sql query to run without considering if the parameters are passed or not in c# windows forms

I am using VS 2012 and SQL Express
I am trying to build a windows forms application to search through a database in C# and it has different controls on the form which are passed as parameters to the query.
The parameters in the query are not necessarily passed some times
I am trying with the following code sample.
SELECT a.ID AS 'DealID', a.TradeDate, c.COMPANYNAME AS 'Seller Company',
a.SellCommission, h.BROKER_FULLNAME AS 'Seller Trader',
j.DisplayName AS 'Seller Broker', d.COMPANYNAME AS 'Buyer Company',
a.BuyCommission, g.BROKER_FULLNAME AS 'Buyer Trader',
i.DisplayName AS 'Buyer Broker', e.PRODUCT_NAME, f.TYPE_DESC AS 'Quantity Type',
f.NBR_OF_GALLONS AS 'Quantity Multiplier', a.ContractVolume, a.TotalVolume,
a.DeliveryPoint, a.Price, a.ContractStart, a.ContractEnd
FROM Confirmations AS a WITH (nolock)
LEFT OUTER JOIN COMPANY AS c WITH (nolock)
ON c.COMPANY_ID = a.SellCompany
LEFT OUTER JOIN COMPANY AS d WITH (nolock)
ON d.COMPANY_ID = a.BuyCompany
LEFT OUTER JOIN BIOPRODUCTTYPES AS e WITH (nolock)
ON e.ID = a.ProductID
LEFT OUTER JOIN BIO_QUANTITY_TYPE AS f WITH (nolock)
ON f.ID = a.QuantityTypeID
LEFT OUTER JOIN COMPANYBROKER AS g WITH (nolock)
ON g.COMPANYBROKER_ID = a.BuyTrader
LEFT OUTER JOIN COMPANYBROKER AS h WITH (nolock)
ON h.COMPANYBROKER_ID = a.SellTrader
LEFT OUTER JOIN Users AS i WITH (nolock)
ON i.ID = a.BuyBroker
LEFT OUTER JOIN Users AS j WITH (nolock)
ON j.ID = a.SellBroker
WHERE (#fromdate IS NULL OR #fromdate=' ' OR a.TradeDate >= #fromdate)
AND (#todate IS NULL OR #todate=' ' OR a.TradeDate <= #todate)
AND (#buycompanyname IS NULL
OR #buycompanyname=""
OR a.BuyCompany = (SELECT COMPANY_ID
FROM COMPANY
WHERE (COMPANYNAME = #buycompanyname)))
AND (#sellcompanyname IS NULL
OR #sellcompanyname=""
OR a.SellCompany = (SELECT COMPANY_ID
FROM COMPANY
WHERE (COMPANYNAME =#sellcompanyname)))
AND (#product IS NULL OR #product="" OR e.PRODUCT_NAME= #product)";
Rather than using the above query, can I dynamically create a query, based on the parameters I passed which seems more logical as it doesn't look for the records if the column in the table has a null value.
This is what ORM's where created for. By replacing your hard coded querys with somthing that builds your query at runtime (like Entity Framework or NHibernate) and it builds the both the SELECT and the WHERE portions of the query for you.
With proper set up objects you could use Entity Framework like the following
Nullable<DateTime> fromDate = //...
Nullable<DateTime> toDate = //...
string buyCompany = //...
//(Snip)
using(var ctx = new MyContext())
{
var query = ctx.Order;
if(fromDate.HasValue)
query = query.Where(ent=> ent.TradeDate >= fromDate.Value);
if(toDate.HasValue)
query = query.Where(ent => ent.TradeDate <= toDate.Value);
if(String.IsNullOrWhitespace(buyCompany) == false)
query = query.Where(ent => ent.BuyCompany.CompanyName = buyCompany);
//(Snip)
return query.ToList();
}
If you are calling a stored procedure, I'd suggest dynamically building the SQL string to only use the parameters you'll be using, then calling sp_executesql. The stored procedure would look like this:
DECLARE #sql =nvarchar(MAX), #Parameters nvarchar(max)
SET #sql = 'SELECT * FROM [dbo].[Foo] WHERE Column1 = #Param1'
SET #Parameters = '#Param1 nvarchar(32), #Param2 nvarchar(32)'
IF(#Param2 is not null and #Param2 <> ' ') SET #sql = #sql + ' AND Column2 = #Param2'
EXEC sp_executesql #Sql, #Parameters, #Param1, #Param2
The idea is basically the same if you're building the query string in C# instead of a stored procedure:
command.CommandText = "SELECT * FROM [dbo].[Foo] WHERE Column1 = #Param1";
command.Parameters.AddWithValue("#Param1", param1);
if(!String.IsNullOrEmpty(param2))
{
command.CommandText += " AND Column2 = #Param2";
command.Parameters.AddWithValue("#Param2", param2);
}
Yes, just build your sql query string out.
Set your SqlCommand.CommandType to CommandType.Text
then set your parameters with SqlCommand.Parameters.AddWidthValue(string, object);

Generate a report from Northwind DB using Linq

I'm trying to generate following report from popular NorthWind DB using Linq. It should be group by Customer, OrderYear.
CustomerName OrderYear Amount
I've to use the following tables Customer,Order and Order Details.
So far this is what I've done.
NorthwindDataContext north = new NorthwindDataContext();
var query = from o in north.Orders
group o by o.Customer.CompanyName into cg
select new
{
Company = cg.Key,
YearGroup = ( from y in cg
group y by y.OrderDate.Value.Year into yg
select new
{
Year = yg.Key,
YearOrdes = yg
}
)
};
foreach (var q in query)
{
Console.WriteLine("Customer Name : " + q.Company);
foreach (var o in q.YearGroup)
{
Console.WriteLine("Year " + o.Year);
Console.WriteLine("Sum " + o.YearOrdes.Sum(yo => yo.Order_Details.Sum( yd=> Convert.ToDecimal(yd.UnitPrice* yd.Quantity))));
}
Console.WriteLine();
}
It is giving me expected results. I compared by running t-sql in back end.But, I've 2 questions.
In the Inner foreach, the 2nd statement generate the sum. Is it proper approach? Or there is better one available?
How to get the Sum in the Linq query itself.
Got it in single LINQ to SQL query:
var query = from o in north.Orders
from c in north.Customers.Where(c => c.CustomerID == o.CustomerID).DefaultIfEmpty()
from d in north.Order_Details.Where(d => d.OrderID == o.OrderID).DefaultIfEmpty()
group new { o, c, d } by new { o.OrderDate.Value.Year, c.CompanyName } into g
select new
{
Company = g.Key.CompanyName,
OrderYear = g.Key.Year,
Amount = g.Sum(e => e.d.UnitPrice * e.d.Quantity)
};
You can then simply get results:
var results = query.ToList();
Or sort it before fetching:
var results = query.OrderBy(g => g.Company).ThenByDescending(g => g.OrderYear).ToList();
I was curious about SQL that is generated by that LINQ to SQL query, so set custom Log and here it is:
SELECT [t5].[value22] AS [Company], [t5].[value2] AS [OrderYear], [t5].[value] AS [Amount]
FROM (
SELECT SUM([t4].[value]) AS [value], [t4].[value2], [t4].[value22]
FROM (
SELECT [t3].[UnitPrice] * (CONVERT(Decimal(29,4),[t3].[Quantity])) AS [value], [t3].[value] AS [value2], [t3].[value2] AS [value22]
FROM (
SELECT DATEPART(Year, [t0].[OrderDate]) AS [value], [t1].[CompanyName] AS [value2], [t2].[UnitPrice], [t2].[Quantity]
FROM [dbo].[Orders] AS [t0]
LEFT OUTER JOIN [dbo].[Customers] AS [t1] ON [t1].[CustomerID] = [t0].[CustomerID]
LEFT OUTER JOIN [dbo].[Order Details] AS [t2] ON [t2].[OrderID] = [t0].[OrderID]
) AS [t3]
) AS [t4]
GROUP BY [t4].[value2], [t4].[value22]
) AS [t5]
ORDER BY [t5].[value22], [t5].[value2] DESC
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.6387
A bit scary, isn't it? But if you look closer, there is standard LEFT JOIN used to combine all three tables together! All the rest is just grouping, sorting and summing.

if condition in IQueryable Join in LINQ query (Convert SQL to LINQ)

As I need to convert following MS SQL Query in to Linq in C#
As I have tryed with IQueryable but not able to do .
As in that we need to check if condition is true then only need to go for join with table
Thanks in adv.
SELECT #sqlQuery = 'SELECT distinct tbl_1.col1 , tbl_1.col2, tbl_1.col3
FROM tbl_1 vd '
if(#Condetion is not null)
BEGIN
set #sqlQuery = #sqlQuery +'
Inner Join
( SELECT vml.*
FROM tbl_2 vml
INNER JOIN tbl_3 vm
ON tbl_1.IDCol = tbl_2.IDCol WHERE tbl_3.Name LIKE ''%'+#Condetion+'%'') A ON A.MessageID = vd.MessageID '
END
set #sqlQuery = #sqlQuery + 'INNER JOIN tbl_4 tbl
ON tbl.ColID12 = vd.ColID12
LEFT OUTER JOIN
vdd_typeid tblVdd ON tblVdd.TypeId=tbl_1.TypeId
INNER JOIN ...... '
EXEC sp_executesql #sqlQuery
As following i have try with LINQ
var query = from VD in _db.GetTable<tbl_1>() select VD ;
if (!string.IsNullOrEmpty(Category.Trim()))
{
query = query.Join((from VML in this._db.GetTable<tbl_1>()
join VM in this._db.GetTable<tbl_2>() on VML.MessageID equals VM.MessageID
where VM.Category.Name(Condetion),VD => new{VD.TypeId == [need write to write like this but can not VML.TypeId] }
}
query = query.Join(from TblVMS_def in this._db.GetTable<tbl_4>() on ........
It is extremely hard to deciper what you actually need, I've had a go here but it would possibly be far simpler with a copy of your Entity Diagram and a concise description of the data you are after.
I've had a go with what I think you want
var cat = string.IsNullOrWhiteSpace(Category) ? null : Category.Trim();
var query = from VD in _db.GetTable<tbl_1>()
join tbl in _db.GetTable<tbl_4>() on tbl.ColID12 equals VD.ColID12
join VM_I in _db.GetTable<tbl_2>() on VD.MessageID equals VM_I.MessageID
from VM in VM_I.DefaultIfEmpty()
where cat == null || VM.Category.Name.Contains(cat)
select new { col1 = VD.col1, col2 = VD.col2, VD.col3 };
you can then do query.Distinct() for distinct values;
Can I suggest that you use LinqPad to work out your query, it's far easier to work with and will also show you the resulting SQL

Categories

Resources