Is there a way to make this in linq? - c#

I'm getting a sum of the checks that have been printed but haven't been cashed yet by checking 2 tabled in the database thru entitiyframework
I have tried multiple queries but I'm not too experienced in LINQ and I'm not getting the desired results, below is some of my implementations.
select sum(checks.Check_Amount) from dbo.ODC_Register checks
left join dbo.vw_BMO_Daily cashed
on checks.Check_Number = cashed.DCheckNo
where cashed.Id is null
and checks.Check_Date < '2019-9-3'
This is what i tried last
var missing = from checks in Context.ODC_Register
where(!Context.vw_BMO_Daily.Where(ma => Convert.ToInt32(ma.DCheckNo) == checks.Check_Number && checks.Check_Date <= ma.DatePosted).Any())
select new {checks.Check_Amount };
var missingSum = missing.Sum( x => x.Check_Amount);
All I need is to find a way to make this into a LINQ query

While a straight forward translation of your SQL is possible, perhaps using the GroupJoin would be a more LINQ friendly approach:
var ans = (from checks in Context.ODC_Register
where checks.Check_Date < new DateTime(2019, 9, 3)
join cashed in Context.vw_BMP_Daily on checks.Check_Number equals cashed.DCheckNo into cashedj
where !cashedj.Any()
select checks.Check_Amount).Sum();
PS Not sure why the range variable for ODC_Register is named checks since it is for one check at a time - I would call it check.
PPS In SQL and LINQ, a not exists test is usually preferable to using an empty left join:
var an2 = (from checks in Context.ODC_Register
where checks.Check_Date < new DateTime(2019, 9, 3)
where !Context.vw_BMP_Daily.Any(cashed => cashed.DCheckNo == checks.Check_Number)
select checks.Check_Amount).Sum();

Related

SQL IN Operator to LINQ

I need this query to be translated to Linq query
SELECT DISTINCT (pf.Id)
FROM
PF pf
LEFT JOIN FA fa on pf.id = fa.PFId
LEFT JOIN Fan f ON pf.FId = f.Id
WHERE
pf.PId=2 AND fa.AId IN (1,26) AND fa.AId NOT IN(27)
This is the LINQ query I have so far as requested
var allFansSavedAsLeads = _dbContext.PF
.Where(e => e.F.S != null &&
e.A.Any(x => x.AId==27 &&
x.AId.Equals(1) /*&&
x.AId != 27*/) &&
e.PId == pId);
I get zero results with this.
I suggest you Create two lists of Ids representing the Activities that can be included and activities which needs to be excluded. use them like the following:
List<int> IncludedIds = new List<int>(){1,26};
List<int> ExcludedIds = new List<int>(){27};
_dbContext.ProfileFans.Where(e => e.Fan.SNUrl != null &&
e.Activities.Any(x => IncludedIds.Any(x.ActivityId) &&
!ExcludedIds.Any(x.ActivityId) &&
e.ProfileId == profileId);
Please note: I used List<int> because of the example that you are given, you have to create the lists based on the data type of ActivityId
You can create a temporary ActivityList AS
var List<int> ActivityList = new List<int>() {1, 26}
and use something like
ActivityList.Contains(x => x.ActivityId)
But see sujith's answer for a more complete solution.
You don't need a whitelist and a blacklist. It's either one or the other. So I'm making a whitelist. If the allowed ActivityId is 1 or 26, then by definition it is definitely not 27, so there is no need to try and exclude it. I'm using int[] instead of List<int> given that the whitelist is likely to be static, but feel free to change this to a List<int> if you want to dynamically modify it.
int[] whiteList = { 1, 26 };
var allFansSavedAsLeads = _dbContext.ProfileFans.Where(pf =>
pf.Fan.SNUrl.HasValue &&
pf.Activities.Any(fa => whiteList.Contains(fa.ActivityId)));
If you want the JOINs as well, you may want to look into .Include(), but from your original SQL query you seem like you're not going to actually need the contents of the joined tables.

SQL to LINQ troubles

I have some SQL which returns two columns, the X column and Y column:
SELECT TOP (100) PERCENT
dbo.SurveyAnswer.QuestionAnswer AS [Y],
COUNT(dbo.SurveyAnswer.QuestionAnswer) AS [X]
FROM
dbo.SurveyAnswer
INNER JOIN dbo.SurveyQuestion ON
dbo.SurveyAnswer.QuestionID = dbo.SurveyQuestion.QuestionID
INNER JOIN dbo.FieldAgentCall ON
dbo.SurveyAnswer.JobId = dbo.FieldAgentCall.JobId AND
dbo.SurveyAnswer.ObjectiveId = dbo.FieldAgentCall.ObjectiveID AND
dbo.SurveyAnswer.AgentId = dbo.FieldAgentCall.AgentID
INNER JOIN dbo.SurveyQuestionaire ON
dbo.FieldAgentCall.JobId = dbo.SurveyQuestionaire.JobId and
dbo.SurveyQuestion.QuestionaireID = dbo.SurveyQuestionaire.QuestionaireID and
WHERE
(dbo.SurveyQuestion.QuestionNo = 9) AND (dbo.SurveyQuestion.QuestionaireID = 1) AND
dbo.SurveyAnswer.QuestionAnswer <>'NA'
GROUP BY
dbo.SurveyAnswer.QuestionAnswer
ORDER BY
[Y]
The SQL searches through a range of tables and returns all the answers to a question and groups then, so the results would look similar to.
X | Y
No | 234
Yes | 43
The SQL works fine, I got that working without a problem, due to the length of the query and different parameters being sent in, the query got to an unmanageable size and decided it's time it became LINQ.
So I am trying to get the basic LINQ working to get results out, but being fairly new to LINQ, I can't quite get it working
var query = (from answers in db.SurveyAnswerModels.ToList()
join question in db.SurveyQuestion.Where(i => i.QuestionID == 9 && i.QuestionaireID == 1).ToList() on answers.QuestionID equals question.QuestionID
join questionnaire in db.SurveyQuestionnaire.ToList() on question.QuestionaireID equals questionnaire.QuestionaireID
join fieldagent in db.FieldAgentCall.ToList() on questionnaire.JobId equals fieldagent.JobId
group answers.QuestionAnswer by answers.QuestionAnswer into results
select new { X = results.Count(), Y = results });
The result I am getting for this is the wrong amount of counts for X and the Y data isn't group
[{"Xs":2814,"Ys":["No","No","No","No",
Though it's the wrong amount because I assume I've not added the right parameters yet, so that's something I can sort, the main problem I am having though is the group by, I tried to replicate it as much as possible but failed.
The "No's" should just be a "No" with the count of how many No's there are, which it's going with the counter as it says there are 2,814 No's, I just need it to only say say "No" once.
Any advice would be great too, like where I am going wrong.
Try this:
var query = (from answers in db.SurveyAnswerModels
join question in db.SurveyQuestion on answers.QuestionID equals question.QuestionID
join questionnaire in db.SurveyQuestionnaire on question.QuestionaireID equals questionnaire.QuestionaireID
join fieldagent in db.FieldAgentCall on questionnaire.JobId equals fieldagent.JobId
where question.QuestionID == 9 && question.QuestionaireID == 1
group answers.QuestionAnswer by answers.QuestionAnswer into results
select new { Count = results.Count(), Answer = results.Key });
Differences from yours:
The ToLists() are removed (this is at best unnecessary and at worst will screw up the C#-expression-to-SQL translation)
Moved the Where() down to the bottom (unnecessary, but makes it easier to follow)
Select results.Key as the answer. Key is the the "grouped by" value for reach result group.
I think 3. is possibly the only step necessary to get it working.

Conditional where clause with date parameters raises a has no supported translation to SQL. error in Linq to SQL with C#

I'm working on a linq to sql project using Visual C# 2008 and dot Net framework 4.5.
my query is as follows
var q =
from a in dc.GetTable<invoice_in>()
join b in dc.GetTable<supplier>()
on a.supplier_id equals b.id
where a.invoice_date >= date_from
select new Invoice_in(a.id, a.amount ?? 0, a.invoice_number ,
a.supplier_id ?? 0, a.supplier.s_name,
a.invoice_date ?? System.DateTime.Today);
invoce_in is a linq class while Invoice_in is a class I defined with a similar structure.
When I put the date comparison inside where clause within the last query, everything is OK. But I need to use a conditional where, as the query parameters goes after the main query clause
I added the following lines to the previous code
if (date_from != null)
{
q = q.Where(w => w.invoice_date >= date_from);
}
Where w.invoice_date is of DateTime type and it is data member of the class Invoice_in (defined by me).
Adding that last lines of code causes the following runtime error:
"has no supported translation to SQL"
I've tried dozens of methods on the web such as using SQLMethods for comparing dates and such stuff, nothing works
Please Help... Thanks in advance...
This should work for you:
var q =
from a in dc.GetTable<invoice_in>()
join b in dc.GetTable<supplier>()
on a.supplier_id equals b.id
select a;
//since you compared date_from against null I assume it is Nullable<DateTime>
if (date_from.HasValue)
{
q = q.Where(a => a.invoice_date >= date_from.Value);
}
var result =
q.Select(a => new Invoice_in(a.id, a.amount ?? 0,
a.invoice_number ,
a.supplier_id ?? 0,
a.supplier.s_name,
a.invoice_date ?? System.DateTime.Today))
.ToList();

Linq to sql query: how to prevent duplication of code

My problem
I'm very new to Linq and I have to difficulties using it. I have written functional queries but I was forced to duplicate some code in every single query. The first part for the queries is just there to give the structure of the database and remove corrupt data, so it always the same and it don't want to have several versions in my code.
What I tried
I made a function returning the portion of the query, but it won't compile and just gives an unexpected token error, so I'm lost.
My code
//always the same in each query : beginning
IQueryable<Lead> query = (from costumers in dc.T_costumers
join demands in dc.T_Demands on costumers.Costumer_FK equals typo.Typoe_PK
where
(dc.ISNUMERIC(costumers.Geoloc) == true) &&
costumers.longitudeClient != null
where (dc.ISNUMERIC(shop.id) == true)
//always the same in each query : end
where (temps.Date > new DateTime(2013, 4, 1).Date)
select new Lead
{
id = Convert.ToInt32(costumers.id),
});
Question
How do I wrote my queries so the common part is written only once in my code?
You can split query. First - select anonymous object with all linked entities:
var query =
from leads in dc.T_DM_FactDemandeWebLeads
join demands in dc.T_DM_DimDemandeWebs
on leads.DemandeWeb_FK equals demands.DemandeWeb_PK
join temps in dc.T_DM_Temps
on demands.DateDemande_FK equals temps.Temps_PK
join distributeurs in dc.T_DM_DimDistributeurs
on leads.Distributeur_FK equals distributeurs.Distributeur_PK
join geographies in dc.T_DM_DimGeographies
on distributeurs.DistributeurGeographie_FK equals geographies.Geographie_PK
join typologies in dc.T_DM_DimTypologies
on leads.Typologie_FK equals typologies.Typologie_PK
where (dc.ISNUMERIC(leads.GeolocDistanceRouteDistrib) == true) &&
leads.longitudeClient != null && typologies.CodeProcessus == "LEAD"
where (dc.ISNUMERIC(distributeurs.DistribIdPointDeVente) == true)
select new {
leads,
demands,
temps,
distributeurs,
geographies,
typologies
};
Second - write specific query:
var leads = from x in query
where (x.temps.Date > new DateTime(2013, 4, 1).Date)
where (x.temps.Date < new DateTime(2013, 5, 30).Date)
select new Lead {
id = Convert.ToInt32(x.leads.DemandeWeb_FK),
});

Why does this additional join increase # of queries?

I'm having trouble coming up with an efficient LINQ-to-SQL query. I am attempting to do something like this:
from x in Items
select new
{
Name = x.Name
TypeARelated = from r in x.Related
where r.Type == "A"
select r
}
As you might expect, it produces a single query from the "Items" table, with a left join on the "Related" table. Now if I add another few similar lines...
from x in Items
select new
{
Name = x.Name
TypeARelated = from r in x.Related
where r.Type == "A"
select r,
TypeBRelated = from r in x.Related
where r.Type == "B"
select r
}
The result is that a similar query to the first attempt is run, followed by an individual query to the "Related" table for each record in "Items". Is there a way to wrap this all up in a single query? What would be the cause of this? Thanks in advance for any help you can provide.
The above query if written directly in SQL would be written like so (pseudo-code):
SELECT
X.NAME AS NAME,
(CASE R.TYPE WHEN A THEN R ELSE NULL) AS TypeARelated,
(CASE R.TYPE WHEN B THEN R ELSE NULL) AS TypeBRelated
FROM Items AS X
JOIN Related AS R ON <some field>
However, linq-to-sql is not as efficient, from your explanation, it does one join, then goes to individually compare each record. A better way would be to use two linq queries similar to your first example, which would generate two SQL queries. Then use the result of the two linq queries and join them, which would not generate any SQL statement. This method would limit the number of queries executed in SQL to 2.
If the number of conditions i.e. r.Type == "A" etc., are going to increase over time, or different conditions are going to be added, you're better off using a stored procedure, which would be one SQL query at all times.
Hasanain
You can use eager loading to do a single join on the server to see if that helps. Give this a try.
using (MyDataContext context = new MyDataContext())
{
DataLoadOptions options = new DataLoadOptions();
options.LoadWith<Item>(i => i.Related);
context.LoadOptions = options;
// Do your query now.
}

Categories

Resources