How do I convert this SQL statement to LINQ to Entities. I cant find a way to union the tables with WHERE clause
SQL:
Declare #DID int, #key varchar(50)
SET #DID = 3
SET #key = ''
SELECT TBL.GID, TBL.GName, TBL.DID FROM
(
SELECT TOP 1 (#DID*10000) AS [GID], '' AS [GName], #DID AS [DID]
FROM dbo.Employees E
WHERE E.DepartmentID=#DID
AND (E.GroupID IS NULL OR E.GroupID = 0)
UNION ALL
SELECT G.GroupID AS [GID], G.GroupName AS [GName], G.DepartmentID AS [DID]
FROM dbo.Groups G
) TBL
WHERE TBL.DID IN (#DID)
AND TBL.GName IN
(
SELECT (CASE WHEN E.GroupID = 0 or E.GroupID IS NULL THEN ''
ELSE (SELECT G.GroupName FROM Groups G WHERE G.GroupID=E.GroupID) END)
FROM Employees E
WHERE E.DepartmentID = #DID
AND (E.FirstName + ' ' + E.LastName) LIKE '%' + #key + '%'
)
ORDER BY TBL.GName DESC
LINQ to Entites:
var Details = (from a in Context.Employees
where a.DepartmentID == DepartmentID
&& (a.GroupID == null || a.GroupID == 0)
select new
{
GID = Convert.ToInt32(DepartmentID * 10000),
GName = "",
DID = a.DepartmentID
}
).Concat(
from a in Context.Groups
select new
{
GID = a.GroupID,
GName = a.GroupName,
DID = DepartmentID
}
);
The anonymous type created in the results of each query are different types, so you can't Concat() them. You could define a common Group class like this...
class Group
{
public int ID { get; set; }
public int DepartmentID { get; set; }
public string Name { get; set; }
}
Then pull out the sub-queries and create the results as instances of the above class...
int deptID = 99;
string key = "foo";
var r1 = (from a in Context.Employees
where a.DepartmentID == deptID
&& (!a.GroupID.HasValue || a.GroupID == 0)
select new Group()
{
ID = a.DepartmentID * 10000,
Name = string.Empty,
DepartmentID = a.DepartmentID
}
).Take(1);
var r2 = (from a in Context.Groups
where a.DepartmentID == deptID
select new Group()
{
ID = a.GroupID,
Name = a.GroupName,
DepartmentID = a.DepartmentID
}
);
var results = r1.Concat(r2); // UNION ALL the above 2 sets of results
Then create the filter set and finally use it filter the results from above...
var filter = (from e in Context.Employees
join g in Context.Groups on g.GroupID equals e.GroupID into eg
from subgrp in eg.DefaultIfEmpty()
where e.DepartmentID == deptID
&& (e.FirstName + " " + e.LastName).Contains(key)
select e.GroupID.HasValue && e.GroupID != 0 ? subgrp.GroupName : string.Empty
).Distinct().ToList();
results = from a in results
where filter.Contains(a.Name)
orderby a.Name descending
select a;
Feel free to comment if doesn't do exactly what you need.
Related
below I have listed a linq query that works properly in my asp.net.mvc web app.
In addition I would like to group over 'allowance.ParameterId' in order to get the group sum for 'allowance.Freight (instead of multiple records for the given key).
var query = from ara in aras
join company in companies on ara.Id equals company.ARAId
join wasteWater in wasteWaters on company.Id equals wasteWater.CompanyId
join allowance in allowances on wasteWater.Id equals allowance.WasteWaterID
join parameter in parameters on allowance.ParameterId equals parameter.Id into JoinedParameterAllowance
from parameter in JoinedParameterAllowance.DefaultIfEmpty()
where company.Activ == true && company.End == null && company.Template == false
&& wasteWater.End == null
select new FreightSummaryViewModel
{
AraName = ara.Name,
AraId = ara.Id,
AllowedParameter = parameter.Name,
AllowedFreight = allowance.Freight
};
I have tried to insert 'group ...' but failed to get it right.
Could someone help me please to set up the proper syntax?
Thank you in advance, Manu
I have little idea about relations in your database, so I improvised...
// Some dummy data to play with
var aras = Enumerable.Range(0, 5).Select(i => new { Id = i, Name = "Ara" + i });
var companies = Enumerable.Range(0, 15).Select(i => new { Id = i, ARAId = i % 5, Activ = true, End = (DateTime?)null, Template = false });
var wasteWaters = Enumerable.Range(0, 35).Select(i => new { Id = i, CompanyId = i / 15, End = (DateTime?)null });
var allowances = Enumerable.Range(0, 70).Select(i => new { Id = i, WasteWaterID = i, ParameterId = i % 4, Freight = i * 1000 });
var parameters = Enumerable.Range(0, 4).Select(i => new { Id = i, Name = "Parameter" + i });
And this is what I believe you looked for:
var query =
from ara in aras
join company in companies on ara.Id equals company.ARAId
join wasteWater in wasteWaters on company.Id equals wasteWater.CompanyId
join allowance in allowances on wasteWater.Id equals allowance.WasteWaterID
join parameter in parameters on allowance.ParameterId equals parameter.Id
into JoinedParameterAllowance
// from parameter in JoinedParameterAllowance.DefaultIfEmpty()
where true
&& company.Activ == true
&& company.End == null
&& company.Template == false
&& wasteWater.End == null
group allowance by new
{
AraName = ara.Name,
AraId = ara.Id,
ParameterId = allowance.ParameterId
} into myGroup
select new //FreightSummaryViewModel
{
AraName = myGroup.Key.AraName,
AraId = myGroup.Key.AraId,
AllowedParameter = myGroup.Key.ParameterId,
AllowedFreight = myGroup.Sum(g => g.Freight)
};
Can you please help to convert this from sql to linq, i am new to linq and been trying this and couldn't succeed. Let me know if this is even possible or not?
SELECT max(Products.ProductID) as ProductID, Products.SKU, Products.Name, Products.RRP, Products.Price,
max(Products.FrontTall) as FrontTall,
ProductsCategory.SortOrder,
Products.ColorValue,
max(Products.ColorImg) as ColorImg,
Products.IsPrimary,
Products.Visible
FROM Products INNER JOIN ProductsCategory ON Products.ProductID = ProductsCategory.ProductID
WHERE (ProductsCategory.CategoryID = 5 ) AND (Products.Visible = 1) AND (Products.Inactive = 0) AND (Products.Deleted = 0 or Products.Deleted is null)
GROUP BY SKU, Products.Name, RRP, Price, ColorValue, ProductsCategory.SortOrder, IsPrimary, Visible
AND this is what i am trying
var products = (from p in db.Products
join cp in db.ProductsCategories on p.ProductID equals cp.ProductID
where cp.CategoryID == catId && p.Visible == true && p.Inactive == false && (p.Deleted == null || p.Deleted == false)
group p by new {
p.SKU,
p.Name,
p.RRP,
p.Price,
p.ColorValue,
p.IsPrimary,
p.Visible,
cp.SortOrder
} into grouped
select new {
ProductID,
FrontTall,
ColorImg,
SKU = grouped.Key.SKU,
Name = grouped.Key.Name,
RRP = grouped.Key.RRP,
Price = grouped.Key.Price,
ColorValue = grouped.Key.ColorValue,
IsPrimary = grouped.Key.IsPrimary,
Visible = grouped.Key.Visible,
SortOrder = grouped.Key.SortOrder
})
.OrderBy(x => x.SortOrder);
I need to get the ProductID, FrontTall and ColorImg field value without including in group by
Thanks in advance.
Kish
select new {ProductID = grouped.Max(x => x.ProductID)}
I have a SQL query :
SELECT [Paypoint]
,[Department]
,[EmployeeCode]
,[Gender]
,[EmployeeTitle]
,[Initials]
,[Surname]
,[ItemsIssuedDate]
,[ItemsIssuedStockNumber]
FROM [MyTable] AS a
WHERE
(
[ItemsIssuedDate] = ( SELECT max([ItemsIssuedDate])
FROM [MyTable] AS b
WHERE a.[Paypoint] = b.[Paypoint]
AND a.[Department] = b.[Department]
AND a.[EmployeeCode] = b.[EmployeeCode]
AND a.[Gender] = b.[Gender]
AND a.[Surname] = b.[Surname]
)
How would one get the comparitive LINQ query ? I cannot use the SQL query as the Data is already in a DataSet, and now needs to be modified further...
I have attempted, but this does not work :
var query = from a in excelTable
where
(
from c in excelTable
group c by new
{
c.Paypoint,
c.EmployeeCode
} into g
where string.Compare(a.Paypoint, g.Key.Paypoint) == 0 && string.Compare(a.EmployeeCode, g.Key.Paypoint) == 0
select g.Key.Paypoint
)
select a;
var query = from a in MyTable
group a by new {
a.Paypoint,
a.Department,
a.EmployeeCode,
a.Gender,
a.Surname
} into g
select g.OrderByDescending(x => x.ItemsIssuedDate)
//.Select(x => new { required properties })
.First();
You can also select anonymous object with required fields only. Up to you.
Your most direct with the SQL query will be:
var query =
from a in excelTable
let maxIssueDate =
(from b in excelTable
where a.Paypoint == b.Paypoint &&
a.Department == b.Department &&
a.EmployeeCode == b.EmployeeCode &&
a.Gender == b.Gender &&
a.Surname == b.Surname
select b.ItemsIssueDate).Max()
where a.ItemsIssueDate == maxIssueDate
select a;
I'm getting a error when this attempts to run:
Nullable<Guid> ng = corpid;
var qry1 = from c in entities.Transactions
join p in entities.Products on c.CorporationId equals (Nullable<Guid>) p.CorporationId
where c.Branch == br &&
c.AccountNumber == accountnumber &&
c.CorporationId == ng
orderby c.TransactionDate descending
select new
{
Date = c.TransactionDate,
RefNo = c.ReferenceNumber,
DlvryAcct = c.DeliveryAccount,
Desc = p.Description,
GasQty = c.GasQuantity,
Total = c.Amount,
Balance = c.Balance
};
This is the message:
LINQ to Entities does not recognize the method
'System.Linq.IQueryable`1[f__AnonymousType1`7[System.Nullable`1[System.DateTime],
System.String,System.String,System.String,System.Nullable`1[System.Decimal],
System.Nullable`1[System.Decimal],System.Nullable`1[System.Decimal]]]
Reverse[f__AnonymousType1`7](System.Linq.IQueryable`1[f__AnonymousType1`7[System.Nullable`1[System.DateTime],
System.String,System.String,System.String,System.Nullable`1[System.Decimal],
System.Nullable`1[System.Decimal],System.Nullable`1[System.Decimal]]])'
method, and this method cannot be translated into a store expression.
I don't think the cast to nullable guid is working here. The c.CorporationId is a nullable guid but the p.corporationid is just a guid.
Any suggestions?
Have you tried foregoing the casting and equating c.CorporationId to ng.Value instead?:
Nullable<Guid> ng = corpid;
var qry1 = from c in entities.Transactions
join p in entities.Products on c.CorporationId equals p.CorporationId
where c.Branch == br &&
c.AccountNumber == accountnumber &&
c.CorporationId == ng.Value
orderby c.TransactionDate descending
select new
{
Date = c.TransactionDate,
RefNo = c.ReferenceNumber,
DlvryAcct = c.DeliveryAccount,
Desc = p.Description,
GasQty = c.GasQuantity,
Total = c.Amount,
Balance = c.Balance
};
It seems to be complaining about the anonymous constructor in the select clause. c.TransactioDate, c.GasQuantity, c.Amount and c.Balance all appear to be Nullable. Try something like this just to see if those fields are the problem.
Nullable<Guid> ng = corpid;
var qry1 = from c in entities.Transactions
join p in entities.Products on c.CorporationId equals (Nullable<Guid>) p.CorporationId
where c.Branch == br &&
c.AccountNumber == accountnumber &&
c.CorporationId == ng.Value
orderby c.TransactionDate descending
select new
{
Date = c.TransactionDate.Value,
RefNo = c.ReferenceNumber,
DlvryAcct = c.DeliveryAccount,
Desc = p.Description,
GasQty = c.GasQuantity.Value,
Total = c.Amount.Value,
Balance = c.Balance.Value
};
This is an old question, but since there's no answer, here's the skinny. In C# Guid is a non-nullable object, so you can't ever map null to Guid, but you can map Null to Guid?, so here's the solution:
var qry1 = from c in entities.Transactions
join p in entities.Products on c.CorporationId equals p.CorporationId
where c.Branch == branch
&& c.AccountNumber == accountNumber
&& ((Guid?)c.CorporationId).Value == null // This is the secret sauce
orderby c.TransactionDate descending
select new
{
Date = c.TransactionDate,
RefNo = c.ReferenceNumber,
DlvryAcct = c.DeliveryAccount,
Desc = p.Description,
GasQty = c.GasQuantity,
Total = c.Amount,
Balance = c.Balance
};
But, I would probably do this:
var qry1 = from c in entities.Transactions.Where(t => ((Guid?)t.CorporationId).Value == null)
join p in entities.Products on c.CorporationId equals p.CorporationId
where c.Branch == branch
&& c.AccountNumber == accountNumber
orderby c.TransactionDate descending
select new
{
Date = c.TransactionDate,
RefNo = c.ReferenceNumber,
DlvryAcct = c.DeliveryAccount,
Desc = p.Description,
GasQty = c.GasQuantity,
Total = c.Amount,
Balance = c.Balance
};
But you have to ask the question if you are having to cast this why the model has this column identified as not being nullable (if it was set right, you probably wouldn't be faced with having to cast at this point).
What is in and not in equals in LINQ to SQL?
For example
select * from table in ( ...)
and
select * from table not in (..)
What is equal to the above statement in LINQ to SQL?
You use, where <list>.Contains( <item> )
var myProducts = from p in db.Products
where productList.Contains(p.ProductID)
select p;
Or you can have a list predefined as such:
int[] ids = {1, 2, 3};
var query = from item in context.items
where ids.Contains( item.id )
select item;
For the 'NOT' case, just add the '!' operator before the 'Contains' statement.
I'm confused by your question. in and not in operate on fields in the query, yet you're not specifying a field in your example query. So it should be something like:
select * from table where fieldname in ('val1', 'val2')
or
select * from table where fieldname not in (1, 2)
The equivalent of those queries in LINQ to SQL would be something like this:
List<string> validValues = new List<string>() { "val1", "val2"};
var qry = from item in dataContext.TableName
where validValues.Contains(item.FieldName)
select item;
and this:
List<int> validValues = new List<int>() { 1, 2};
var qry = from item in dataContext.TableName
where !validValues.Contains(item.FieldName)
select item;
Please Try This For SQL Not IN
var v = from cs in context.Sal_Customer
join sag in context.Sal_SalesAgreement
on cs.CustomerCode equals sag.CustomerCode
where
!(
from cus in context.Sal_Customer
join
cfc in context.Sal_CollectionFromCustomers
on cus.CustomerCode equals cfc.CustomerCode
where cus.UnitCode == locationCode &&
cus.Status == Helper.Active &&
cfc.CollectionType == Helper.CollectionTypeDRF
select cus.CustomerCode
).Contains(cs.CustomerCode) &&
cs.UnitCode == locationCode &&
cs.Status == customerStatus &&
SqlFunctions.DateDiff("Month", sag.AgreementDate, drfaDate) < 36
select new CustomerDisasterRecoveryDetails
{
CustomerCode = cs.CustomerCode,
CustomerName = cs.CustomerName,
AgreementDate = sag.AgreementDate,
AgreementDuration = SqlFunctions.DateDiff("Month", sag.AgreementDate, drfaDate)
};
Please Try This For SQL IN
context.Sal_PackageOrItemCapacity.Where(c => c.ProjectCode == projectCode && c.Status == Helper.Active && c.CapacityFor.Contains(isForItemOrPackage)).ToList();