how to use 'IN' clause in linq [duplicate] - linq

This question already has answers here:
Where IN clause in LINQ [duplicate]
(8 answers)
Closed 8 years ago.
public static List<mainISRC> comedianlist(int iid)
{
List<mainISRC> newlst = new List<mainISRC>();
ISRCManagementDBEntities1 dbcontext = new ISRCManagementDBEntities1();
newlst=(from z in dbcontext.Comedians
where !(from b in dbcontext.mainISRCs
where b.id==iid && b.Actor1==z.Comedian1 || b.Comedian1==z.Comedian1 || b.Comedian3==z.Comedian1 || b.Comedian4==z.Comedian1).Any()
select z.Comedian1).ToList();
return newlst;
}
I have a table name "comedian" with column 'id','Comedian' and 'IsActive' which contain 50 numbers of rows and also I have another table name "mainISRC" with column 'id','Actor1','Actor2','Actor3','Actor4'. 'id' column in "actorlist" and 'iid' column in "addrecord" are not same.
I have to find all those 'comedian' from "comedian" which are not in 'Actor1','Actor2','Actor3','Actor4' column. What will be the Linq query for this?

Final Update Code
Sorry code is not tested but it may help you or gives you a direction
List<int> liComedianId = new List<int> ();
liComedianId = dbcontext.Comedians.Select(s => (int)s.Id).ToList();
List<mainISRC> limainISRC = new List<mainISRC> ();
limainISRC = dbcontext.mainISRCs.ToList();
var d = ((from a in limainISRC.Select(s => s.Actor1).ToList()
select a).TolList().Union
(from b inlimainISRC.Select(s => s.Actorb).ToList()
select b).Tolist()).ToList();
d = d.Distinct();
licomedianId = licomedianId.Select(s => !d.Contain(s));
List<comedian> LIcomedianFinal = new List<comedian> ();
LIcomedianFinal = dbcontext.Comedians.ToList();
var FinalList =(from a in LIcomedianFinal .ToList()
join b in d.TolIst()
on a.Id equlas d).ToList();

Related

Problem with iterating over two lists simultaneously

I'm using ASP.NET Core 3.1. I have written some code like the following and now I want to get the result of these two queries that has the same size and iterate over each one of them and divide their element and store the result in a list. But now the problem is in my zip method, I can not specify exactly which attribute of each query I want to divide.
var mytotal = _context.Apiapp.GroupBy(o => new
{
Month = o.ApiRequestDate.Substring(4, 2),
Year = o.ApiRequestDate.Substring(0, 4)
}).Select(g => new
{
Month = g.Key.Month,
Year = g.Key.Year,
Total = g.Count()
}).OrderByDescending(a => a.Year).ThenByDescending(a => a.Month).ToList();
var numerator = from t1 in _context.Apiapp
join t2 in _context.ApiAppHistory on t1.Id equals t2.ApiApplicantId
join t3 in _context.EntityType on t2.LastReqStatus equals t3.Id
where t1.IsDeleted == false && t1.LastRequestStatus == t2.Id && t3.Name == "granted"
group new { Year = t1.ApiRequestDate.Substring(0, 4), Month = t1.ApiRequestDate.Substring(4, 2) }
by new { t2.LastReqStatus } into g
select new
{
Year = g.Max(n => n.Year),
Month = g.Max(n => n.Month),
GrantedCount = g.Count()
};
var GrantedReqStatus = numerator.ToList();
var GrantedAccessPercent = new List<Double>();
//-------------------------------------------------------
var res = mytotal.Zip(GrantedReqStatus, (total, GrantedCount) => new { Num = total, Denum = GrantedCount });
foreach(var r in res)
{
GrantedAccessPercent.Add(r.Num/r.Denum);
}
Here inside the body of foreach, r.Num and r.Denum is unknown! I appreciate of any help to fix the error.
The Num and DemNum in the Zip function represent objects for the first and second collection, that contains Month,Year and Total for the total object and Month,Year and GrantedCount for the grantedCount object.
You could use total.Total and grantedCount.GrantedCount to get numbers, like the following code:
var res = mytotal.Zip(GrantedReqStatus, (total, grantedCount) => new { Num = total.Total, Denum = grantedCount.GrantedCount });
foreach(var r in res)
{
GrantedAccessPercent.Add(Math.Round(r.Num / (double)r.DemNum, 2));
}
Note that, to divide int1/int2 you need to cast int2 to double, Will give the expected result, and you can use also Math.Round to specify numbers after comma.
I hope this help you fix the issue.

How can I get a random record in LINQ to SQL when Guid doesnt work [duplicate]

This question already has answers here:
linq select a random row
(6 answers)
Closed 3 years ago.
I want to select 1 random record. I use LINQ to SQL for my query, but im not really familiar with these (I know normal SQL queries better)
This is my code:
public void giveRand()
{
var query = (from Performance in db.Performances.OrderBy(c => Guid.NewGuid()).Take(1)
join Stage in db.Stages on Performance.stage_id equals Stage.stage_id
join Artist in db.Artists on Performance.artist_id equals Artist.artist_id
select new AllClass(db)
{
all_performance_id = Performance.performance_id,
all_starttime = Performance.starttime,
all_endtime = Performance.endtime,
all_artistname = Artist.name,
all_stagename = Stage.name,
all_artistdesc = Artist.description,
all_stagedesc = Stage.description
}).Single();
App.Current.Properties["timestart"] = query.all_starttime;
App.Current.Properties["timeened"] = query.all_endtime;
App.Current.Properties["namea"] = query.all_artistname;
App.Current.Properties["names"] = query.all_stagename;
App.Current.Properties["desca"] = query.all_artistdesc;
App.Current.Properties["descs"] = query.all_stagedesc;
}
I dont know whats wrong.
I'd follow the advice from the comment and rewrite a bit the query.
But, to answer your question, you can use Skip(random)+Take(1):
Random r = new Random();
int n = // number of records
var record = ... /* linq query */ .Skip(r.Next(0, n)).Take(1)

Get null for empty collection in LINQ Group

I am working on LINQ query and part of objective to do SQL database call once to achieve result. I have number of questions which may have collection of answers.
I need to choose all the questions and collection of answer and if there no answer for specific question, I still need it.
for code gives me only question which have answer but not ones without answer
var t3 = (Context.Answers
.Include(answer => answer.AnswerStatusType)
.Where(answer => Context.Questions.Where(q => q.profileId == ProfileId)
.Any(t => t.Id == answer.QuestionId)))
.GroupBy(
x => x.QuestionId,
x => x,
(key, g) => new
{
Question = key,
Answers = g.ToList(),
}
).ToList();
You probably need something like this:
var t3 =
(
from q in Context.Questions
where q.profileId == ProfileId
join a in Context.Answers on q.Id equals a.QuestionId into gas
select new
{
Question = q,
Answers = gas.ToList(),
}
).ToList();
I had the exact same problem and solved it with this giant query, which could probably be optimized, but maybe it will help someone with a similar problem.
// Perform left join to get all the questions (even those that don't have answers)
var results = (from quiz in db.Quizzes
join question in db.Questions on quiz.QuestionID equals question.QuestionID
from answer in db.QuestionAnswers.Where(a => question.QuestionID == a.QuestionID).DefaultIfEmpty()
where quiz.QuizID == quizId
group (answer != null ? new AnswerVM()
{
AnswerId = answer.AnswerID,
AnswerText = answer.AnswerText,
Correct = question.CorrectAnswerID != null ? answer.AnswerID == question.CorrectAnswerID : false,
} : null) // For the questions with no answers
by new
{
question.QuestionID,
question.DisplayOrder,
question.QuestionText,
question.CorrectAnswerID
} into g
select new QuestionVM
{
QuestionId = g.Key.QuestionID,
QuestionText = g.Key.QuestionText,
CorrectAnswerId = g.Key.CorrectAnswerID,
Answers = g.ToList()
})
.AsEnumerable()
.Select(x => {
// If there are no answers then group by will return the list with one value (null),
// then we need to change the answers list to be null (not the list with one null value)
if (x.Answers.Count(a => a != null) <= 0)
{
x.Answers = null;
}
return x;
}).ToList();

how use multiple join in linq?

var abc1 = from dlist in db.DebtorTransactions.ToList()
join war in db.Warranties on dlist.ProductID equals war.Id
join ag in db.Agents on war.fldAgentID equals ag.pkfAgentID
join sr in db.SalesReps on war.fldSrId equals sr.pkfSrID
where dlist.TransTypeID == 1
select new
{
dlist.Amount,
dlist.TransTypeID,
name = ag.Name,
ag.pkfAgentID,
sr.pkfSrID,
salesnam = sr.Name
} into objabc
group objabc by new
{
objabc.TransTypeID,
objabc.name,
objabc.salesnam,
objabc.Amount
};
var amt1 = abc1.Sum(x => x.Key.Amount);
var abc2 = from dlist in db.DebtorTransactions.ToList()
join cjt in db.CarJackaTrackas on dlist.ProductID equals cjt.pkfCjtID
join ag in db.Agents on cjt.AgentID equals ag.pkfAgentID
join sr in db.SalesReps on cjt.SalesRepId equals sr.pkfSrID
where dlist.TransTypeID == 0
select new
{
dlist.Amount,
dlist.TransTypeID,
name = ag.Name,
ag.pkfAgentID,
sr.pkfSrID,
enter code here` salesnam = sr.Name
} into objabc
group objabc by new
{
objabc.TransTypeID,
objabc.name,
objabc.salesnam,
objabc.Amount
};
var amt2 = abc1.Sum(x => x.Key.Amount);
//var result1=
return View();
i am new to linq, this query is working but i need to get the sum of Amount where dlist.TransTypeID == 0 and where dlist.TransTypeID == 1 by just single query. may anybody help me? thanks in advance
Here's a trimmed down example of how you can do it. You can add the joins if they are necessary, but I'm not clear on why you need some of the extra join values.
var transTypeAmountSums = (from dlist in db.DebtorTransactions
group dlist by dlist.TransTypeId into g
where g.Key == 0 || g.Key == 1
select new
{
TransTypeId = g.Key,
AmountSum = g.Sum(d => d.Amount)
}).ToDictionary(k => k.TransTypeId, v => v.AmountSum);
int transTypeZeroSum = transTypeAmountSums[0];
int transTypeOneSum = transTypeAmountSums[1];
A couple of things to note:
I removed ToList(). Unless you want to bring ALL DebtorTransactions into memory then run a Linq operation on those results, you'll want to leave that out and let SQL take care of the aggregation (it's much better at it than C#).
I grouped by dlist.TransTypeId only. You can still group by more fields if you need that, but it was unclear in the example why they were needed so I just made a simplified example.

Linq to Sql Query - better solution (optimizing)

The following code works, but it's not a nice code. (low performance)
I have a dictionary with value and key.
First i go trough every webcodes who exist. Then i load all participants in a list (where webcode equals the actual webcode in the foreach). After that i add the data (parameter of the webcode and a count of participants to the dictionary).
Guid compID = Guid.Parse(wID);
ChartModel webcodes = new ChartModel();
webcodes.Title = "Webcodes Statistics";
webcodes.Data = new Dictionary<string, int>();
var webcodesData = db.t_Webcode;
foreach (var w in webcodesData)
{
var wData = db.t_Participant.Where(t => t.FK_Competition == compID && t.Webcode == w.Webcode);
if (wData.Count() != 0)
webcodes.Data.Add(w.Parameter, wData.Count());
}
ViewBag.Webcodes = webcodes;
TIA
You need something along these lines:
webcodes.Data = (from w in db.t_Webcode
join p in db.t_Participant on w.Webcode equals p.Webcode
where p.FK_Competition == compID
group w by w.Parameter into g
select new { g.Key, Count = g.Count() }).ToDictionary();
I can't test it but that is the type of query you need.
This will assume that you have relationships defined in your database and that your LINQ to SQL datacontext are aware of them. If not, you will need to join manually on t_Participants from tWebcode.
This should execute in 1 single SQL query, instead of 1 query per row in tWebcode.
var webcodesAndNoOfParticipants =
from webcode in db.tWebcode
// Define number of participants for this webcode
let numberOfParticipants = webcode.t_Participants.Count(participant => participant.FK_Competition == compID)
where numberOfParticipants > 0
select new {
WebcodeParameter = webcode.Parameter,
NoOfParticipants = numberOfParticipants
};
webcodes.Data = webcodesAndNoOfParticipants.ToDictionary(x => x.WebcodeParameter, x => x.NoOfParticipants);

Resources