Joining a list of classes - linq

Hi guys i have two lists of the class Student
List<Student> group1= new List<Trade>();
List<Student> group2= new List<Trade>();
public class Student
{
public string First_Name{ get; set; }
public string Surname{ get; set; }
public string Age{ get; set; }
}
i would like to do a join that enables me to see those that are only in 1 group.
ideal output being a datatable with column 1 showing those that only in group1 and column2 representing those only in group2
any help would be really appreciated. I am struggling to get my head around joins

Use Except:-
var onlyInGroup1 = group1.Except(group2);
var onlyInGroup2 = group2.Except(group1);
Please note, since Student is a complex type, you need to implement IEqualityComparer<Student>.
Also, I missed your list initialization, as pointed by #Hamlet, it should be something like this:-
List<Student> group1= new List<Student>();
List<Student> group2= new List<Student>();

you could iterate thru group1 and see if group2 contains a match to group1
foreach (Student student in group1)
{
if (group2.Contains(student.First_Name))
{
//logic goes here
}
}

Related

ICollection properties Sorting in ASP.Core using LINQ

How to sort Icollection properties.For example:
public class INSTRUCTOR
{
public int Id
public string Name
public PersonalDetails PersonalDetail
}
public class PersonalDetails
{
public int Id;
public string Firstname;
public ICollection<Emails> Emails;
}
public class Emails
{
public int Id;
public string Email;
}
Now I have the list pages of instructor and I got all instructors like this:
var instructors = db.instructors.include(p=>p.personaldetails).Tolist();
I can sort using instructorName using the following Code:
instructors = instructors.OrderBy(i => i.PersonalDetail.Firstname).ToList();
But, I want to know how to do with using emails which is ICollection?
In some way you're going to have to flatten the Email collection in order to sort the parent collection by it, either by applying some aggregate function or by for example joining it into a string.
If you for example make the assumption that the first Email address in the list is the primary address, then it could make sense to sort only by this item;
var orderedList =
instructors.OrderBy(i => i.PersonalDetails.Emails.FirstOrDefault()?.EmailAddress).ToList();
You could also choose to order by the "smallest" email address in the list by applying the Min() aggregate function;
var orderedList =
instructors.OrderBy(x => x.PersonalDetails.Emails.Min(e => e.EmailAddress)).ToList();

What is the way to write the new get and set properties in C# 6.0 when has more sentences?

in the last C# versions of the properties get and set with more sentences the way to write is:
ObservableCollection<Product> products;
public ObservableCollection<Product> Products
{
get
{
return products;
}
set
{
products = value;
OnPropertyChanged("Products");
}
}
But how is that in C# 6.0? because the new style is with lambda operator:
ObservableCollection<Product> products;
public ObservableCollection<Product> Products
{
get => products;
set => products= value;
}
Thanks.
The Auto-Implemented Properties (auto-properties) have existed since c# 3.
public int Age { get; set; }
C# 6 do some improvements, one of them was the Auto-Property Initializers.
public int Age { get; } = 30;
But I think what you want to use is another feature, the Expression-bodied function members
public void SayHello(string name) => Console.WriteLine("hello {0}", name);
public string FullName => string.Format("{0} {1}", FirstName, LastName);
Expression-bodied function members
The body of a lot of members that we write consist of only one statement that can be represented as an expression. You can reduce that syntax by writing an expression-bodied member instead. It works for methods and read-only properties.
Expression-bodied function members
You can't use use them in your case, because your property is not read-only.
Maybe this can help you.
How to implement INotifyPropertyChanged in C# 6.0?
UPDATE:
C# 7 introduces the syntax you want, but only for single-line expressions.
Property set statements(link)
If you choose to implement a property set accessor yourself, you can use an expression body definition for a single-line expression that assigns a value to the field that backs the property.
public class Location
{
private string locationName;
public Location(string name) => Name = name;
public string Name
{
get => locationName;
set => locationName = value;
}
}

Linq Query Return Error

I cannot figure out why my return from a linq query always is not correct.
[HttpGet]
public List<Programs> GetPrograms()
{
using (var context = new ProgramsDataContext1())
{
var qry = (from a in context.Programs
join b in context.courselist on a.Prog_id equals(b.prog_id)
where a.Prog_id ==b.prog_id
orderby a.Programname
select new
{ Prog_id =a.Prog_id,Programname=a.Programname, programlevel=a.programlevel, planname=a.planname, catalogNo=b.catalogNO, coursetitle=b.coursetitle, subject=b.subject
}
).ToList();
return qry ;
}
}
It always has a red underline on the qry. What is the problem here? Thanks.
Since you are doing the join already, you do not need the where clause. Also your return type is not the same, that's the error you are getting. You are right now returning a list of anonymous objects, not Programs
Just define a class that lists just the properties you need from the two classes and instead of building an anonymous object create instances of this class.
public class ProgramsCourseDto
{
public int Prog_id {get;set;}
public string Programname {get;set;}
public int programlevel {get;set;}
public string planname {get;set;}
public int catalogNo {get;set;}
public string coursetitle {get;set;}
public string subject {get;set;}
}
[HttpGet]
public List<ProgramsCourseDto> GetProgramsCourses()
{
using (var context = new ProgramsDataContext1())
{
var qry = (from a in context.Programs
join b in context.courselist on a.Prog_id equals(b.prog_id)
orderby a.Programname
select new ProgramsCourseDto
{
Prog_id =a.Prog_id,
Programname=a.Programname,
programlevel=a.programlevel,
planname=a.planname,
catalogNo=b.catalogNO,
coursetitle=b.coursetitle,
subject=b.subject
}).ToList();
return qry ;
}
}

OrderBy using RavenDB-an exception

I use Raven Db in my project. Im trying to order list like below:
list.OrderByDescending(x => x.Supporters.Sum(y=>y.Tokens));
And i got an exception like this:
{"Unable to cast object of type 'System.Linq.Expressions.MethodCallExpressionN' to type 'System.Linq.Expressions.MemberExpression'."}
Model looks as below:
public class Idea
{
(...)
public IList<IdeaSupporter> Supporters { get; set; }
}
public class IdeaSupporter
{
(...)
public int Tokens { get; set; }
}
What do i wrong?
Thanks for any help.
You cannot sort on a computation, but you can define an index like this:
from idea in docs.Ideas
select new
{
SumOfSupportersTokens = idea.Supporters.Sum(x=>x.Tokens)
}
And then sort on SumOfSupportersTokens

Problem passing data from repository to viewmodel

I have the following viewmodel,
public class SiteAdminCreateViewModel
{
public Customer Customer { get; private set; }
public CustomerSite CustomerSite { get; private set; }
public SelectList CustomerNames { get; private set; }
public SiteAdminCreateViewModel(CustomerSite customerSite, Customer customer)
{
CustomerSite = customerSite;
Customer = customer;
CustomerNames = new SelectList(customer.CustomerName);
}
}
And the following methods in my repository for returning a list of customers and a list of CustomerSites
public IQueryable<CustomerSite> GetCustomerSites
{
get { return context.CustomerSites; }
}
public IQueryable<Customer> GetCustomers
{
get { return context.Customers; }
}
When i instanitiate the viewmodel in my controller im wanting to return the list of customers to passs to the select list in the viewmodel.
public ViewResult Create()
{
CustomerSite customerSite = new CustomerSite();
var customer = repository.GetCustomers.ToList();
return View(new SiteAdminCreateViewModel(customerSite, customer));
}
But the return line throws the error
cannot convert from System.Collections.Generic.List' to 'CustomerOrders.Domain.Entities.Customer
I think this is because i have the customer variable defined in the Viewmodel of type Customer but im trying to pass a list of customers?
Can anyone offer any advice on where i am going wrong here?
Do i need to define both the Customer type and the CustomerNames select list type in the viewmodel, i defined the Customer Object only so i can use it to pass the Customers to the select list but im not sure if this is the best way to do this?
Any advice anyone can offer for a newbie, will be much appreciated.
Your SiteAdminCreateViewModel class' constructor is defined as follows:
public SiteAdminCreateViewModel(CustomerSite customerSite, Customer customer) {
...
}
Its second argument is of type Customer.
You're passing var customer = repository.GetCustomers.ToList() to it, whose type is List<Customer>.
When i instanitiate the viewmodel in my controller im wanting to
return the list of customers to passs to the select list in the
viewmodel.
If I understand what you're saying correctly, you're just trying to pass the customers list to build a SelectList.
First of all, you seem to be passing a string to the SelectList constructor. This would not even compile (read System.Web.Mvc.SelectList).
What you'd need to do is change SiteAdminCreateViewModel's constructor like
public SiteAdminCreateViewModel(CustomerSite customerSite, IEnumerable<Customer> customers) {
/* ... */
CustomerNames = new SelectList(customers, "CustomerId", "CustomerName");
}
CustomerId and CustomerName being properties of the Customer class.
it's simply because you are trying to pass IList into constructor of the SiteAdminCreateViewModel
var customer = repository.GetCustomers.ToList();
return View(new SiteAdminCreateViewModel(customerSite, customer));
using
var customer = repository.GetCustomers.ToList().FirstOrDefault();
return View(new SiteAdminCreateViewModel(customerSite, customer));
would work, also you may need to check if the customer is null

Resources