I am trying to concat and comma deliminated (or space) a list and project it. I have some sample code below.
public class Friend
{
public string Name { get; set; }
}
public class Person
{
public int PersonID { get; set; }
public string FirstName { get; set; }
public string Surname { get; set; }
List<Friend> Friends { get; set; }
}
public class ProjectedPerson
{
public int PersonID { get; set; }
public string FirstName { get; set; }
public string Surname { get; set; }
public string FriendsList { get; set; }
}
public class Test
{
public void MyTest()
{
var query = from p in MyDataStore.Person
select p;
var results = from q in query
select new ProjectedPerson
{
PersonID = q.PersonID,
FirstName = q.FirstName,
Surname = q.Surname,
FriendsList = q.FriendsList.Concat() //??? How can I concat this and return a string
};
}
}
Use string.Join (note that the list will need to be in memory first), to concatentate the selected properties from your Friend objects. If you are using .NET 3.5, you'll need to use ToArray() as well as the overloads on string.Join in 3.5 require an array.
var query = (from p in MyDataStore.Person
select p).ToList(); // <-- bring into memory with ToList()
var results = from q in query
select new ProjectedPerson
{
PersonID = q.PersonID,
FirstName = q.FirstName,
Surname = q.Surname,
FriendsList = string.Join( ", ", q.Friends.Select( f => f.Name ) )
};
string.Join is the better way but abusing LINQ is just so fun.
var query = (from p in MyDataStore.Person
select p).ToList(); // <-- bring into memory with ToList()
var results = from q in query
select new ProjectedPerson
{
PersonID = q.PersonID,
FirstName = q.FirstName,
Surname = q.Surname,
FriendsList = q.Friends.Aggregate<Friend, string>(null, (accum, f) => accum + (accum == null ? accum : ", ") + f.Name)
};
Related
I am trying to group together daily logs into months in a linq query from a dbset, getting above or below a percentage of allowed usage.
The dbset is on
public partial class DailyUsageForYear
{
public System.DateTime DateAdded { get; set; }
public Nullable<long> NumUsers { get; set; }
public int AllowedUsageCount { get; set; }
public string Application { get; set; }
public System.Guid ApplicationID { get; set; }
public System.Guid SupplierID { get; set; }
}
I am trying the to get a list of objects like
public class UsageDisplay
{
public int Year { get; set; }
public int Month { get; set; }
public string Application { get; set; }
public int NumUsers { get; set; }
public int AllowedUsageCount { get; set; }
public Guid ApplicationID { get; set; }
}
However the select at the end of my statement does not seem to understand the field names, can anyone tell me please, what am I missing about the linq syntax?
var predicate = PredicateBuilder.False<DailyUsageForYear>();
predicate = predicate.And (x => x.NumUsers > (x.AllowedUsageCount * (DropPercentage/100)));
if (supplier != null)
{
Guid supplierGuid = new Guid (supplier.ToString());
predicate = predicate.And (x => x.SupplierID == supplierGuid);
}
if (Direction == 0)
predicate = predicate.And (x => x.NumUsers < (x.AllowedUsageCount * (Percentage/100)));
else
predicate = predicate.And (x => x.NumUsers > (x.AllowedUsageCount * (Percentage/100)));
usageDetailModel.usage = db.DailyUsageForYears.**Where**(predicate)
.**GroupBy**(x => new { x.DateAdded.Year, x.DateAdded.Month, x.Application, x.NumUsers, x.SeatCount, x.LicenceID })
.**Select**(u => new UsageDisplay() { Year = u.DateAdded.Year, Month = u.DateAdded.Month, Application = u.Application, NumUsers = u.NumUsers, SeatCount = u.SeatCount, ApplicationId = u.ApplicationID });
Inside last select u is not DailyUsageForYear its groupping object with Key field, so try change your select like this
.Select(u => new UsageDisplay() {
Year = u.Key.Year,
Month = u.Key.Month,
Application = u.Key.Application,
NumUsers = u.Key.NumUsers,
SeatCount = u.Key.SeatCount,
ApplicationId = u.Key.ApplicationID
});
also in
.GroupBy(x => new {
x.DateAdded.Year,
x.DateAdded.Month,
x.Application,
x.NumUsers,
x.SeatCount,
x.LicenceID })
i think you need x.ApplicationId instead of x.LicenceID
I'm getting this error at running time:
Exception Details: System.InvalidOperationException: Unhandled binding type: ListBinding
Choice_A, _b,_C are strings
'Choices' is List
var qs = (from questions in dc.Survey_Questions
where questions.Survey_ID == surveyid
select new SQuestions
{
QuestionID = questions.Question_ID,
Description = questions.Description,
Choice_A = questions.Choice_A,
Choice_B = questions.Choice_B,
Choice_C = questions.Choice_C,
**Choices = {questions.Choice_A, questions.Choice_B,
questions.Choice_C}**
}).ToList();
Basically I'd like to know how I assign to List Choices values of Choice_A,Choice_B, Choice_C.
Thanks in advance.
You can try this. If you already have the following two classes
public class Question
{
public int Question_ID { get; set; }
public int Survey_ID { get; set; }
public String Description { get; set; }
public String Choice_A { get; set; }
public String Choice_B { get; set; }
public String Choice_C { get; set; }
}
public class SQuestions
{
public int QuestionID { get; set; }
public String Description { get; set; }
public String Choice_A { get; set; }
public String Choice_B { get; set; }
public String Choice_C { get; set; }
public List<String> Choices { get; set; }
}
Then the LINQ Query will be
var qs = (from question in dc.Survey_Questions
where question.Survey_ID == surveyid
select new SQuestions
{
QuestionID = question.Question_ID,
Description = question.Description,
Choice_A = question.Choice_A,
Choice_B = question.Choice_B,
Choice_C = question.Choice_C,
Choices = new List<string>(new String[] { question.Choice_A,question.Choice_B, question.Choice_C })
}).ToList();
LINQ to Entities does not support this binding syntax. You should be able to do this, though:
qs = (from questions in dc.Survey_Questions
where questions.Survey_ID == surveyid
select new SQuestions
{
QuestionID = questions.Question_ID,
Description = questions.Description,
Choice_A = questions.Choice_A,
Choice_B = questions.Choice_B,
Choice_C = questions.Choice_C,
Choices = new List<string> {questions.Choice_A, questions.Choice_B,
questions.Choice_C}
}).ToList();
I want to get the sum of applicants that applied to a specific position, this should not be saved as a column.
My model is simple:
We have positions:
net developer
java developer
We have applicants:
Luis
John
etc
We have applicants per position
With this column or property I want to know how many people have applied to each position, depending on the status.
So in my mvc view I want to show something like:
Position Applied Accepted Rejected ... other status
.net developer 5 3 2
java developer 3 2 1
The real problem here is the linq query which I am not very expert.
EDIT: I think I needed to change where the linq query must be coded, I suppose it should be in the ApplicantPosition class instead of Position, I also changed the types of Position and Application to be ICollection.
Please see the modified code.
public class Position
{
public int id { get; set; }
[StringLength(20, MinimumLength=3)]
public string name { get; set; }
public int yearsExperienceRequired { get; set; }
}
public class Applicant
{
public int ApplicantId { get; set; }
[StringLength(20, MinimumLength = 3)]
public string name { get; set; }
public string telephone { get; set; }
public string skypeuser { get; set; }
public ApplicantImage photo { get; set; }
}
public class ApplicantPosition
{
public virtual ICollection<Position> appliedPositions { get; set; }
public virtual ICollection<Applicant> applicants { get; set; }
public DateTime appliedDate { get; set; }
public int StatusValue { get; set; }
public Status Status
{
get { return (Status)StatusValue; }
set { StatusValue = (int)value; }
}
[NotMapped]
public int numberOfApplicantsApplied
{
get
{
var query =
from ap in appliedPositions
select new
{
positionName = g.Key.name,
peopleApplied = g.Count(x => x.Status == Status.Applied),
};
return query.Count(); ---??
}
}
}
Use direct SQL with PIVOT operator. This is really not a case for Linq query.
You can paste this into LINQPad as C# Program and run.
public enum Status
{
Applied,
Accepted,
Rejected
}
public class Position
{
public int id { get; set; }
public string name { get; set; }
}
public class Applicant
{
public int ApplicantId { get; set; }
public string name { get; set; }
}
public class ApplicantPosition
{
public Position appliedPosition { get; set; }
public Applicant applicant { get; set; }
public DateTime appliedDate { get; set; }
public Status Status { get; set; }
}
void Main()
{
var p1 = new Position { id = 1, name = ".net developer" };
var p2 = new Position { id = 2, name = "java developer" };
var a1 = new Applicant { ApplicantId = 100, name = "Luis" };
var a2 = new Applicant { ApplicantId = 200, name = "John" };
var ap1 = new ApplicantPosition { appliedPosition = p1, applicant = a1, Status = Status.Applied };
var ap2 = new ApplicantPosition { appliedPosition = p1, applicant = a2, Status = Status.Accepted };
var ap3 = new ApplicantPosition { appliedPosition = p2, applicant = a2, Status = Status.Rejected };
var db = new[] { ap1, ap2, ap3};
var query =
from ap in db
group ap by ap.appliedPosition into g
select new
{
positionName = g.Key.name,
peopleApplied = g.Count(x => x.Status == Status.Applied),
peopleAccepted = g.Count(x => x.Status == Status.Accepted),
peopleRejected = g.Count(x => x.Status == Status.Rejected),
};
query.Dump();
}
The result will be:
positionName peopleApplied peopleAccepted peopleRejected
.net developer 1 1 0
java developer 0 0 1
According to my experiences you can use LinQ or Entity Framework just by mapping your tables in to a DBML to a Entity Framework Model file.
In other way Microsoft gives you a Dynamic LinQ class that you can use it.I think you map all your columns and user Dynamic LinQ class.Good luck
I have two list of different columns, but each list have a common column with the same key, how do I combine them into a new list, i.e:
public class TradeBalanceBreak
{
public int CommID { get; set; }
public int CPFirmID { get; set; }
public double CreditDfferenceNotional { get; set; }
public string Currency { get; set; }
}
public class Commission
{
public int CommID { get; set; }
public PeriodStart { get; set; }
public ResearchCredit { get; set; }
}
public class CommissionList
{
public List<Commission> Commissions { get { return GetCommissions(); }}
private List<Commission> GetCommissions()
{
// retrieve data code ... ...
}
}
public class TradeBalanceBreakModel
{
public List<TradeBalanceBreak> TradeBalanceBreaks { get; set; }
}
public class CommissionModel
{
public List<CommissionList> CommissionLists { get; set; }
}
What I would like to achieve is to combine/flatten the TradeBalancesBreaks and CommissionLists (from the model classes) into one. The CommID is shared between the two.
Thanks.
Using Join (extension method version) -- after your update
var list1 = GetTradeBalanceBreaks();
var list2 = new CommisionsList().Commissions;
var combined = list1.Join( list2, l1 => l1.ID, l2 => l2.First().ID,
(l1,l2) = > new
{
l1.CommID,
l1.CPFirmID,
l1.CreditDifferenceNotional,
l1.Currency,
PeriodStarts= l2.SelectMany( l => l.PeriodStart ),
ResearchCredits = l2.SelectMany( l => l.ResearchCredit )
})
.ToList();
var combined = from p in PhoneNumbers
join a in Addresses on a.ID equals p.ID
select new {
ID = p.ID,
Name = p.Name,
Phone = p.Phone,
Address = a.Address,
Fax = a.Fax
};
I have a abstract Class where a Recipient either can be a EMailRecipient or a SMSRecipients.
Im selecting the data out in a List like List<Recipient>. For statistic reason i need to know then number of recipients based on the CountryCode in the SMSRecipient and i thought i could do that in linq. But i cant seem to cast a Recipient as a SMSRecipient like
var q = from v in AMessageQueueContentList
group v by (FlexyNet.Data.SMSRecipient)v.Recipient into g
select count(g);
My class looks like this:
public abstract class Recipient
{
public int MemberID { get;set;}
public Recipient(){}
}
public class EMailRecipient : Recipient
{
public string EMail { get; set; }
public bool ValidMail { get; set; }
public EMailRecipient(FlexyDataReader read)
{
this.MemberID = (int)read["MemberID"];
this.EMail = (string)read["Recipient"];
}
public EMailRecipient(int memberID,string eMail)
{
this.MemberID = memberID;
this.EMail = (string)eMail;
}
}
public class SMSRecipient : Recipient
{
public string Number { get; set; }
public string CountryCode { get; set; }
public nimta.Recipient NimtaRecipient { get; set; }
}
Could you do something like this?
var counts = from m in AMessageQueueContentList
let s = m.Recipient as FlexyNet.Data.SMSRecipient
where s != null
group s by s.CountryCode into g
select new { CountryCode = g.Key, Count = g.Count() };
Or if you actually have a list of Recipient objects, you could use LINQ's OfType<T>() extension method:
var sms = recipients.OfType<FlexyNet.Data.SMSRecipient>();
var counts = from s in sms
group s by s.CountryCode into g
select new { CountryCode = g.Key, Count = g.Count() };