Replacing old sql written in asp.net with Linq - c#

I was trying to replace SQL code with LINQ in order to migrate in to MVC ,but i don't know how to use subquery in LINQ.As of now i have replaced inner sql query with LINQ,i would like to know how to do with outer query.
Following is the SQL query
SELECT
DISTINCT GP_REGION.REGION_MAIN Region_Code,
R1.REGION_NAME
FROM
GP_REGION
INNER JOIN GP_REGION R1 ON GP_REGION.REGION_MAIN = R1.REGION_CODE
WHERE
GP_REGION.REGION_HAS_DATA = 'Y'
AND
GP_REGION.REGION_MAIN IN
(
SELECT
DISTINCT AR.BRANCH_CODE
FROM
PORTAL.UA_APPLN_ROLE AR
INNER JOIN PORTAL.UA_GROUP G ON AR.GROUP_CODE = G.GROUP_CODE
WHERE
G.USER_ID = '" + Global.UserId() + "' AND AR.APPLICATION_ID = '" + ApplicationId + "'
)
ORDER BY
GP_REGION.REGION_MAIN
Here the inner query i have replaced as shown below by using following LINQ
var regions = from p in db3.UA_APPLN_ROLE.AsEnumerable()
join i in db3.UA_GROUP.AsEnumerable()
on p.GROUP_CODE equals i.GROUP_CODE
where
i.USER_ID == Global.UserId()
&&
p.APPLICATION_ID == ConfigurationManager.AppSettings["ApplicationId"]
select new
{
branchcode = p.BRANCH_CODE
};
But i would like to know the outer sql query how can i replace and join with existing LINQ code i wrote

You combine the subquery into the main query as follows:
var efQuery = from gp in db3.GP_REGION
join r1 in db3.GP_REGION on gp.REGION_MAIN equals r1.REGION_CODE
where regions.Contains(gp.REGION_MAIN)
&& gp.REGION_HAS_DATA = "Y"
select new
{
Region_Code = gp.REGION_MAIN,
Region_Name = r1.REGION_NAME
};
var queryResult = efQuery.Distinct().OrderBy(x => x.Region_Code);
You can speed the processing up a bit by using .AsNoTracking(), e.g. db3.GP_REGION.AsNoTracking().
In general it's a good idea to monitor the generated SQL query to avoid situations where it looks simple in code, but is transformed into bad SQL.
But in my opinion the advantages of having the query a first class member in your code (compared to SQL in strings) outweigh the sometimes non-intuitive generated SQL.

Related

Using 'OR' inside a LinQ join query (adapting SQL into LinQ)

I have a SQL query that basically joins the MyWords table to the MyTranslations table on two keys. Here are my tables for better understanding.
MyWords table:
Id
WordString
LangType
MyTranslations table:
Id
WordColumnAId
WordColumnBId
Please note that WordColumnAIdand WordColumnBId columns are FKs that represents the MyWords.Id.
My SQL query:
SELECT MyTranslations.Id
,WordColumnAId
,WordColumnBId
,MyWords.WordString
,MyWords.LangType
FROM MyTranslations
join MyWords on (MyTranslations.WordColumnAId = MyWords.Id or MyTranslations.WordColumnBId = MyWords.Id)
where MyWords.LangType !=#currentLangType
I know it doesn't make sense to use join on with multiple keys at first glance but I'm trying to a cross-query that would join two tables whether the key is on WordColumnAId or WordColumnBId.
Problem
I'm trying to adapt the above T-SQL query into a LinQ query. The problem is that I can't find my way around LinQ to use two keys in a single join query.
Here's what I've got so far:
from translation in queryableTranslation
join word in _myWordRepository on translation.WordColumnAId equals word.Id // This is where I want to add `or translation.WordColumnBId equals word.Id` but get errors.
where word.LangType != currentLangType
select new QueryResultDto {
MyTranslationId = translation.Id,
WordString = word.WordString,
LanguageType = word.LangType,
WordColumnAId = translation.WordColumnAId,
WordColumnbId=translation.WordColumnbId,
};
I'm very new to the LinQ and trying to learn.
So my question: is there a way to achieve this in LinQ or am I trying the impossible? I'm also open to better approaches.
EF and other LINQ providers should translate query to INNER JOIN when using this syntax:
var query =
from translation in queryableTranslation
from word in _myWordRepository.Where(word => translation.WordColumnAId == word.Id
|| translation.WordColumnBId = word.Id)
where word.LangType != currentLangType
select new QueryResultDto
{
MyTranslationId = translation.Id,
WordString = word.WordString,
LanguageType = word.LangType,
WordColumnAId = translation.WordColumnAId,
WordColumnbId=translation.WordColumnbId,
};

LINQ join with multiple conditions of different kind

I'm trying to translate following T-SQL query into LINQ:
SELECT * FROM table_A JOIN table_B ON table_A.key = table_B.key AND
table_A.Trouble <> table_B.Trouble
Stackoverflow is full with similar questions, but in my case there are two conditions but each of them has different operator ("equals to" and "not equals to"). Is there any way to get the same result using LINQ?
You can't use the join syntax, you have to use a where clause to connect the two
var query = from a in table_A
from b in table_B
where a.key = b.key &&
a.Trouble != b.Trouble
select new { a, b };
You can also write this query. It should be work fast
var query = from a in table_A
from b in table_B.where(x=>x.key==a.key && x.Trouble != a.Trouble)
select new { a, b };

Linq Join variable scoping issue

Really odd issue that I cant work out.
I am trying to join two tables in a linq statement to only retrieve records where the record in table 1 has no related rows in table 2.
I have used Joins before but for some reason I cant get VS to recognise the second table in the linq statement.
EG.
var result =
(from pc in _dataSource.Payments
join bc in _dataSource.BouncedCheques
on pc.PaymentID != bc.PaymentID //This is where the error occurs, VS does not recognise "bc"
where pc.CustomerNumber == getAccountNumber
& pc.IsDeleted == false
orderby pc.PaymentDate descending
select new PaymentAllocation
{
PaymentId = pc.PaymentID,
PaymentDate = pc.PaymentDate,
CustomerNumber = pc.CustomerNumber,
ChequeReference = pc.ChequeReference,
PaymentValue = pc.PaymentValue,
AllocatedValue = pc.AllocatedValue,
UnallocatedValue = pc.PaymentValue - pc.AllocatedValue,
ReceivedBy = pc.ReceivedBy,
PaymentType = pc.PaymentType,
PostedDate = pc.PostedDate
});
Basically the problem is that the variable "bc" does not seem to be recognised, however I have several other similar Linq queries that all work well
Any ideas?
Your problem is that the syntax for join uses the keyword equals and not standard boolean operators.
Try replacing your join by a cartesian product of your tables:
from pc in _dataSource.Payments
from bc in _dataSource.BouncedCheques
where
pc.PaymentID != bc.PaymentID
&& pc.CustomerNumber == getAccountNumber
& pc.IsDeleted == false
In the join clause you should use the equals keyword:
try:
on pc.PaymentID equals bc.PaymentID

LEFT LINQ TO SQL C# JOIN on many to many table

Hi im kinda new to linq to sql I know about the basics. The problem is I want to do a left join in a query. There are 3 tables in the query.
Claimants ( all rows should be returned from this table)
Claim
User
The query should return all Users who have Claimants. This is done through the many to many table Claim. But regardless of Users all Claimants should be returned. Thus the left join on Claimants.
I have the following query
var d = (from Claimants in DB.Claimants
join Claims in DB.Claims on Claimants.Claiment_ID equals Claims.Claiment_ID
join Users in DB.Users on Claims.User_ID equals Users.User_ID
where (Claimants.TrialDate.Value >= dtDayStart & Claimants.TrialDate <= dtDayEnd)
select new
{
ClaimantFirstName = Claimants.FirstName,
ClaimantLasname = Claimants.LastName,
ClaimantsID = Claimants.IDNumber,
Claimants.OurReference,
Claimants.TrialDate,
InterviewStart = Claims.DateTimeStart,
InterviewEnd = Claims.DateTimeEnd,
Claims.Priority,
UserFirstname = Users.FirstName,
UserLastName = Users.LastName,
UserID = Users.IDNumber
});
I have tried using an into statement as follows but with no luck
var d = (from Claimants in DB.Claimants
join Claims in DB.Claims on Claimants.Claiment_ID equals Claims.Claiment_ID
into TheClaimants
from Claims in TheClaimants.DefaultIfEmpty()
join Users in DB.Users on Claims.User_ID equals Users.User_ID
where (Claimants.TrialDate.Value >= dtDayStart & Claimants.TrialDate <= dtDayEnd)
select new
{
ClaimantFirstName = Claimants.FirstName,
ClaimantLasname = Claimants.LastName,
ClaimantsID = Claimants.IDNumber,
Claimants.OurReference,
Claimants.TrialDate,
InterviewStart = Claims.DateTimeStart,
InterviewEnd = Claims.DateTimeEnd,
Claims.Priority,
UserFirstname = Users.FirstName,
UserLastName = Users.LastName,
UserID = Users.IDNumber
});
I would appreciate it if someone could point me in the right direction as to how to use these joins left right correctly and explain how the work. Thank you very much in advance.
var d = (from Claimants in DB.Claimants
join Claims in DB.Claims on Claimants.Claiment_ID equals Claims.Claiment_ID)
.DefaultIfEmpty()
join Users in DB.Users on Claims.User_ID equals Users.User_ID
where (Claimants.TrialDate.Value >= dtDayStart & Claimants.TrialDate <= dtDayEnd)
.DefaultIfEmpty()
select new
{
ClaimantFirstName = Claimants.FirstName,
ClaimantLasname = Claimants.LastName,
ClaimantsID = Claimants.IDNumber,
Claimants.OurReference,
Claimants.TrialDate,
InterviewStart = Claims.DateTimeStart,
InterviewEnd = Claims.DateTimeEnd,
Claims.Priority,
UserFirstname = Users.FirstName,
UserLastName = Users.LastName,
UserID = Users.IDNumber
});
Left outter join
You must know a Luan. If you want all the Claiments to return start by selecting from Claiments and then left join onto the other tables.
Try the following :
LINQ to SQL Left Outer Join
In LINQ, the ".Join()" extension method is the equivalent of SQL inner join.
For outer joins you have to use the ".GroupJoin()" extension method.
Assuming you know the .Join well, the GroupJoin is simple to use. I have to admit that when I first needed to do an outer join in LINQ it was damn hard to find out. I cannot fanthom why did they call it like that.
Although in VB.Net, here's an article that presents various SQL constructs translated into LINQ syntax, even if in VB, still easy to convert to extension methods: http://blogs.msdn.com/b/vbteam/archive/2007/12/31/converting-sql-to-linq-part-6-joins-bill-horst.aspx?Redirected=true
EDIT: #DavidB posted in his comments a much better solution, but only if you can use some ORM navigational properties. If you don't have them, then GroupJoin is probably the most reasonable

LINQ to SQL join with LINQ to DataSet

I have a SQL database that I'm using LINQ to connect to (LINQ To SQL) and a local set of XML data (in a dataset). I need to perform an outer left join on the SQL table "tblDoc" and dataset table "document" on the keys "tblDoc:sourcePath, document:xmlLink". Both keys are unfortunately strings. The code I have below doesn't return any results and I've tried a few variations but my LINQ skills are limited. Does anyone have any suggestions or alternate methods to try?
DataColumn xmlLinkColumn = new DataColumn(
"xmlLink",System.Type.GetType("System.String"));
xmlDataSet.Tables["document"].Columns.Add(xmlLinkColumn);
foreach (DataRow xmlRow in xmlDataSet.Tables["document"].Rows)
{
xmlRow["xmlLink"] = (string)xmlRow["exportPath"] +
(string) xmlRow["exportFileName"];
}
var query =
from t in lawDataContext.tblDocs.ToList()
join x in xmlDataSet.Tables["Document"].AsEnumerable()
on t.SourceFile equals (x.Field<string>("xmlLink"))
select new
{
lawID = t.ID,
xmlID = x == null ? 0 : x.Field<int>("id")
};
foreach (var d in query.ToArray())
{
Debug.WriteLine(d.lawID.ToString() + ", " + d.xmlID.ToString());
}
The join clause produces standard inner join behavior. To get an outer join, you need to use the DefaultIfEmpty() extension method:
var query = from t in lawDataContext.tblDocs.ToList()
join x in xmlDataSet.Tables["Document"].AsEnumerable()
on t.SourceFile equals (x.Field<string>("xmlLink"))
into outer
from o in outer.DefaultIfEmpty()
select new
{
lawID = t.ID,
xmlID = o == null ? 0 : o.Field<int>("id")
};

Categories

Resources