Can Any one help me to convert this sql query into linq - sql-server

I need to convert this SQL Query to Link :
"Select * FROM [Register]
where RegisterId IN (SELECT MyId
FROM Friends
WHERE FriendId='" + Session["CurrentProfileId"] + "'
AND Status=1
UNION
SELECT FriendId
FROM Friends
WHERE MyId='" + Session["CurrentProfileId"] + "'
AND Status=1) ";
It may be look like this??? but this is incorrect and having errors
(from u in db.Register
where RegisterId).Contains
(from f in db.Freinds
where f.MyId == Id && m.Status == 1
select new { m.MyId })
.Union(from m in db.Freinds
where f.FreindId == Id && m.Status == 1
select new { m.CreateDate } ));

You have a few problems with the linq above and here are a few:
In the query in the Union you select the CreateDate whereas in the top on you select the MyId. I assume you meant to select FreindId.
In these 2 queries you create an anonymous class instance with the field but then compare it to the RegisterId which is probably a guid/string/int - but for sure not of the type you just created.
You are using the Contains method wrong. Linq syntax can be similar to sql but it is not the same. Check here for Contains
The correct Linq way of doing it is:
var idsCollection = ((from f in db.Freinds
where f.StatusId == 1 && f.MyId == Id
select f.MyId)
.Union(from m in db.Friends
where m.StatusId == 1 && f.FreindId == Id
select m.FriendId)).ToList();
var result = (from u in db.Register
where idsCollection.Contains(u.RegisterId)
select u).ToList();
Notice that the .ToList() is not a must and is here just to ease in debugging. For more information about this .ToList() and Linq in general check MSDN

Related

EF6 query that behaves strangely using contains

I have an EF6 SQL Server query that behaves strangely when it is supplied with a List<int> of IDs to use. If bookGenieCategory = a value it works. If selectedAges is empty (count = 0) all is well. If the selectedAges contains values that exist in the ProductCategory.CategoryId column, the contains fails and NO rows are returned.
Note: AllocationCandidates is a view, which works properly on its own.
CREATE VIEW dbo.AllocationCandidate
AS
SELECT
p.ProductID, p.SKU as ISBN, p.Name as Title,
pv.MSRP, pv.Price, pv.VariantID, pv.Inventory,
ISNULL(plt.DateLastTouched, GETDATE()) AS DateLastTouched,
JSON_VALUE(p.MiscText, '$.AgeId') AS AgeId,
JSON_VALUE(p.MiscText, '$.AgeName') AS AgeName
FROM
dbo.Product AS p WITH (NOLOCK)
INNER JOIN
dbo.ProductVariant AS pv WITH (NOLOCK) ON pv.ProductID = p.ProductID
LEFT OUTER JOIN
dbo.KBOProductLastTouched AS plt WITH (NOLOCK) ON plt.ProductID = p.ProductID
WHERE
(ISJSON(p.MiscText) = 1)
AND (p.Deleted = 0)
AND (p.Published = 1)
AND (pv.IsDefault = 1)
GO
Do I have a typo here or a misplaced parenthesis in the following query?
var returnList = (from ac in _db.AllocationCandidates
join pc in _db.ProductCategories on ac.ProductID equals pc.ProductID
where (bookGenieCategory == 0
|| bookGenieCategory == pc.CategoryID)
&&
(selectedAges.Count == 0 ||
selectedAges.Contains(pc.CategoryID))
orderby ac.AgeId, ac.DateLastTouched descending
select ac).ToList();
Firstly, I would recommend extracting the conditionals outside of the Linq expression. If you only want to filter data if a value is provided, move the condition check outside of the Linq rather than embedding it inside the condition. This is generally easier to do with the Fluent Linq than Linq QL. You should also aim to leverage navigation properties for relationships between entities. This way an AllocationCandidate should have a collection of ProductCategories:
var query = _db.AllocationCandidates.AsQueryable();
if (bookGenieCategory != 0)
query = query.Where(x => x.ProductCategories.Any(c => c.CategoryID == bookGenieCategory);
The next question is what does the selectedAges contains? There is an Age ID on the AllocationCandidate, but your original query is checking against the ProductCategory.CategoryId??
If the check should be against the AllocationCandidate.AgeId:
if (selectedAges.Any())
query = query.Where(x => selectedAges.Contains(x.AgeID));
If the check is as you wrote it against the ProductCategory.CategoryId:
if (selectedAges.Any())
query = query.Where(x => x.ProductCategories.Any(c => selectedAges.Contains(c.AgeID)));
Then add your order by and get your results:
var results = query.OrderBy(x => x.AgeId)
.ThenByDescending(x => x.DateLastTouched);
.ToList();

Create a joined Key-Value in LinqToSql

I have a GridView binded to LinqToSql-DataSource. The DataSource is Multiple-Join. I need unique Key-Values for the Grid. But all PrimaryKeys from the Tables could exist double or not because of left joins.
I have solved the problem in a pure sql-statement. There i create a ID for the TableRows by joining two PrimaryKeys an connecting with a "-". I need one of the IDs for later working with TableRows, the other could be null.
So I do in SQL-Statement:
select CAST(mitgliedschaft.id as varchar(MAX)) + '-' + CAST(ISNULL(funktion.id, '') as varchar(MAX)) as id from ...... inner join ...... etc
I need the CASTS for not producing Calculating with the "-" and the ISNULL-Function because the second ID could be Null.
Now I have to transfer this part of the scenario into Linq-Statement. I tried like this:
...
...
select new
{
...
id = mitgliedschaft.id.ToString() + "-" + (funktion.id == null ? 0 : funktion.id).ToString()
...
});
But didn't get it running in that way. Can someone help me concatenating an ID with "-" and an ID that can be NULL? If it is NULL it should be an empty String or Null-Digit or whatever.
got it now:
select new
{
id = (mitgliedschaft.id.ToString() + "-") + (funktion.id.ToString() ?? "0")
}

SQL how to check prefix in cell with two prefixes

I am learning SQL and I have a table where there are certain cells with two prefixes like this :
example1(cell) : R:8days; U:5$;
example2(cell) : R:8days;
example3(cell) : U:5$;
I want to check for that U:5$ after the first prefix, as I know how to check for prefix R:8days;. So I need to check for U:5$ and then make a new column in table.
My code looks like this:
;with cte as (
select
Employer, AmountPayd, AmountPayd as Payd
from data
where TipeOfTransaction like 'Offline Prepaid%' AND Note like '%R:8%' **HERE I WANT TO CHECK FOR PREFIX NR2. 'U:5$' AND MAKE NEW COLUMN FOR WHICH EMPLOYER HAS U:5$ NOTE.**
)
select
Employer,
[4.00] = ISNULL([4.00],0)
,[5.00] = ISNULL([5.00],0)
,[9.00] = ISNULL([9.00],0)
,[10.00] = ISNULL([10.00],0)
,[15.00] = ISNULL([15.00],0)
,[Sum] =ISNULL([4.00],0) + ISNULL([5.00],0) + ISNULL([9.00],0) + ISNULL([10.00],0) + ISNULL([15.00],0)
from cte
pivot (
sum(AmountPayd) for Payd in ([4.00],[5.00],[9.00], [10.00], [15.00], [20.00]))pvt;
This?
select
Employer, AmountPayd, AmountPayd as Payd,
CASE WHEN Note like '%R:8%;%U:5$%' THEN 'U:5' END U5Note
from data
where TipeOfTransaction like 'Offline Prepaid%' AND Note like '%R:8%'
(I've corrected some mistakes in column names and refactored the query.)
I believe, you are looking for something like this:
WITH CTE AS (
SELECT
Employer,
AmountPaid,
Paid
FROM Data
LEFT JOIN (VALUES (4, 5, 9, 10, 15, 20)) V(Paid)
ON Note LIKE '%U:' + CAST(Paid AS VARCHAR(10)) + '$;%'
WHERE TypeOfTransaction LIKE 'Offline Prepaid%'
AND Note LIKE '%R:8%'
)
SELECT
Employer,
ISNULL([4.00], 0) AS [4.00],
ISNULL([5.00], 0) AS [5.00],
ISNULL([9.00], 0) AS [9.00],
ISNULL([10.00], 0) AS [10.00],
ISNULL([15.00], 0) AS [15.00],
ISNULL([4.00] + [5.00] + [9.00] + [10.00] + [15.00], 0) AS Sum
FROM CTE
PIVOT( SUM(AmountPaid)
FOR Paid IN ([4.00],[5.00],[9.00], [10.00], [15.00], [20.00])) PVT;

Linq query count

select count(tblVV.VNme) as total,
tblvV.VNme
from tblVV
inner join tblRV
on tblVV.MID=tblRV.ID
inner join tblRe
on tblRV.RID=tblRe.RID
where tblRe.StartDate>= '2016-07-01 00:00:00' and
tblRe.EndDate<= '2016-07-31 23:59:59' and
tblRe.Reg= 'uk' and
tblRV.RegNo='BR72' and
tblVV.VNme <>''
group by tblVV.VNme
For the above query I get:
total Vame
1 DDSB
11 MV
The above SQL query shows me correct data so now i try to convert above query to linq query
[WebMethod]
public static string GetVo(string RegNo)
{
string data = "[";
try
{
Ts1 DB = new Ts1();
var re = (from vehvoila in DB.tblVV
join regveh in DB.tblRV on vehvoila.MID equals regveh.ID
join reg in DB.tblReg on regveh.RID equals reg.RID
where regveh.RegNo == RegNo &&
vehvoila.Vame != ""
group vehvoila by vehvoila.Vame into g
select new
{
VNme = g.Key,
cnt = g.Select(t => t.Vame).Count()
}).ToList();
if (re.Any())
{
data += re.ToList().Select(x => "['" + x.Vame + "'," + x.cnt + "]")
.Aggregate((a, b) => a + "," + b);
}
data += "]";
}
linq query show me return data like this
[['DDSB',1],['DPSB',1],['DSB',109],['MV',39],['PSB',1]]
Whereas I want data this
[['DDSB',1],['MV',11]]
Now the data which return SQL query is correct so how I correct linq query
Note: forget fromdate,todate,region parameter in SQL query . because I have page in which I put dropdown and fromdate and todate picker and there is button so when I select values i.e. UK, and dates then data is display in table then when I click on any row in table then I want to get this data in data +=”]”;
actually above linq query work behind clicking on row
total Vame
1 DDSB
11 MV
You can write it all like this:
Ts1 db = new Ts1();
var result = (from vehvoila in db.tblVV
join regveh in db.tblRV on vehvoila.MID equals regveh.ID
join reg in db.tblReg on regveh.RID equals reg.RID
where reg.StartDate >= new DateTime(2016, 7, 1) &&
reg.EndDate < new DateTime(2016, 8, 1) &&
reg.Reg == "uk" &&
regveh == "BR72" &&
vehvoila != ""
group vehvoila by vehvoila.Vame into g
select $"[{g.Key},{g.Count()}]");
var data = $"[{string.Join(",", result)}]";
Because you only use the result for the creation of the string in the select I just return the string formatted for a single item and then later used string.Join instead of using the .Aggregate - I think a bit cleaner
The $"{}" syntax is the C# 6.0 string interpolation
In the condition of the EndDate I decided to use < instead of the <= with the change of the date - At least in oracle when you partition the table by date it is better for performance - maybe also in sql server
Without string interpolation:
Ts1 db = new Ts1();
var result = (from vehvoila in db.tblVV
join regveh in db.tblRV on vehvoila.MID equals regveh.ID
join reg in db.tblReg on regveh.RID equals reg.RID
where reg.StartDate >= new DateTime(2016, 7, 1) &&
reg.EndDate < new DateTime(2016, 8, 1) &&
reg.Reg == "uk" &&
regveh == "BR72" &&
vehvoila != ""
group vehvoila by vehvoila.Vame into g
select new { Key = g.Key, Count = g.Count()})
.AsEnumerable()
.Select(g => string.Format("[{0},{1}]",g.Key, g.Count));
var data = string.Format("[{0}]",string.Join(",", result));

SQL to LINQ Expression

I have specific SQL expression :
{
select * from courceMCPD.dbo.Contact c
where c.cID in ( select cId from courceMCPD.dbo.Friend f where f.cId=5)
}
i would like to get LINQ expression that gets the same result.
thank you in advance.
That sounds like it's equivalent to something like:
var friendIds = from friend in db.Friends
where friend.ContactId == 5
select friend.ContactId;
var query = from contact in db.Contacts
where friendIds.Contains(contact.Id)
select contact;
(There are lots of different ways of representing the query, but that's the simplest one I could think of.)
It's pretty odd to perform a join on a particular field and also mandate that that field has to have a particular value though... there's not very much difference between that and:
var query = db.Contacts.Where(c => c.Id == 5);
... the only difference is whether there are any friend entries for that particular contact.
EDIT: Smudge gave another option for the query in a comment, so I'm promoting it into this answer...
var query = db.Contacts.Where(c => c.Friends.Any(f => f.cId == 5))
This assumes you've got an appropriate Friends relationship defined in the Contacts entity.
Using labda expressions:
var query = dc.Contact
.Where(c => dc.Friend.Select(f => f.cId).Contains(i.cID))
.Where(c => c.cId == 5);
User "query" syntax:
var query = from c in dc.Contact
where (from f in dc.Friend select f.cID).Contains(c.cId)
where c.cId == 5
select c;
You haven't specified VB/C# so I'm going for VB =P
Dim results As IEnumerable(Of yourEntities.Contact) =
(From c In yourContextInstance.Contacts Where (From f In yourContextInstance.Friends
Where f.cId = 5 Select f.cId).Contains(c.cID))
Clearly, Jon's answer works, this query (I believe) just resembles your T-SQL Closer.

Resources