For example, I have class
public class Team
{
public string Name {get;set;}
public string Location {get;set;}
public List<Player> PList{get;set;}
}
And class Player
public class Player
{
public string FirstName {get;set;}
public string LastName {get;set;}
public int Age {get;set;}
}
Please tell me, how should I perform a select from List of Team objects, to get new object:
public class TeamPlayer
{
public string TeamName {get;set;}
public string TeamLocation {get;set;}
public string PlayerFirstName {get;set;}
public string PlayerFirstName {get;set;}
public int PlayerAge {get;set;}
}
For example I've got
var TList = new List<Team>
{
new Team() {
Name = "Rostov",
Location = "Rostov-on-Don",
PList = new List<Player>
{
new Player(){ FirstName = "Soslan", LastName = "Djanaev", Age = 28 },
new Player(){ FirstName = "Christian", LastName = "Noboa", Age = 29 }
}
};
And I want TList to become a List
required selection can be performed with SelectMany method (query syntax is more compact)
var items = from a in aList
from b in a.BList
select new
{
Field1 = a.A1,
Field2 = a.A2,
Field3 = b.B1,
Field4 = b.B2,
Field5 = b.B3
};
Related
I have two lists: List a, List b
var a1= new A
{
Name = "XYZ",
Id = "123"
};
var a2= new A
{
Name = "UVW",
Id = "567"
};
var a = new List<A>()
{
a1,
a2
};
public class A
{
public string Name{ get; set; }
public string Id{ get; set; }
}
var b1= new B
{
Location = "US",
Id = "123"
};
var b2= new B
{
Location = "IN",
Id = "567"
};
var b = new List<B>()
{
b1,
b2
};
public class B
{
public string Location{ get; set; }
public string Id{ get; set; }
}
Notice that Id is common in both A and B classes. The final goal is to have a list that contains values of members from both A and B classes:
var output = new List<AB>()
{
ab1,
ab2
}
public class AB
{
public string Id{ get; set; }
public string Name { get; set; }
public string Location { get; set; }
}
Or update List a to include values from List b?
How would I do that in C#?
You could use Join to get common data based on Id and populate AB, like the following code :
var output = aList.Join(bList,
a => a.Id,
b => b.Id,
(a, b) => new AB
{
Id = a.Id,
Location = b.Location,
Name = a.Name
}).ToList();
Demo
foreach(var item in output)
{
Console.WriteLine($"Id:{item.Id}, Name : {item.Name}, Location:{item.Location}");
}
Result:
Id:123, Name : XYZ, Location:US
Id:567, Name : UVW, Location:IN
Demo in dotnetfiddle : https://dotnetfiddle.net/3ZbK6c
I hope you find this helpful.
Query result from search
Greetings, i am new using linq syntax and i need help translating the query in the picture to get the needed result in c#. I have two questions. First of all How do i do inner joins using linq syntax in c# in order to get the desired result showed in the image. Second, in order to show the data obtained from the query, do i need to create a ViewModel that has 3 ViewModels from the different tables used in the query search?
Thank you so very much for your help.
As levelonehuman said, linq is designed to query data. lets say you have a couple classes:
public class Person
{
public static class Factory
{
private static int currentId = 0;
public static Person Create(string firstName, string lastName, string phoneNumber, int companyId)
{
return new Person()
{
Id = ++currentId,
FirstName = firstName,
LastName = lastName,
PhoneNumber = phoneNumber,
CompanyId = companyId
};
}
}
public int Id { get; private set; }
public string FirstName { get; private set; }
public string LastName { get; private set; }
public string PhoneNumber { get; private set; }
public int CompanyId { get; private set; }
}
public class Company
{
public static class Factory
{
private static int companyId=0;
public static Company Create(string name, string city, string state, string phoneNumber)
{
return new Company()
{
Id = ++ companyId,
City = city,
State = state,
Name = name,
PhoneNumber = phoneNumber
};
}
}
public int Id { get; set; }
public string Name { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PhoneNumber { get; set; }
}
and then you want to see only people from a certain area code you could do something like this:
class Program
{
static void Main(string[] args)
{
var companies = new[]
{
Company.Factory.Create("ABC", "Indianapolis", "In", "(317) 333 5555"),
Company.Factory.Create("Def", "Bloominton", "In", "(812) 333 5555"),
};
var people = new[]
{
Person.Factory.Create("Jane", "Doe", "(317) 555 7565", 1),
Person.Factory.Create("Paul", "Smith", "(812) 555 7565", 2),
Person.Factory.Create("Sean", "Jackson", "(317) 555 7565", 2),
Person.Factory.Create("Jenny", "Gump", "(812) 555 7565", 1)
};
var peopleFromIndianapolis =
(
from company in companies
join person in people on company.Id equals person.CompanyId
where person.PhoneNumber.StartsWith("(317)")
orderby person.LastName, person.FirstName
select new
{
person.FirstName,
person.LastName,
company.Name
}
).ToList();
foreach (var person in peopleFromIndianapolis)
{
Console.WriteLine($"PersonName: {person.LastName}, {person.FirstName} - Company:{person.Name}");
}
}
}
Hope this helps!
I'm trying to build a sub-query by using expression-trees. In linq I would write something like:
var single = MyTable
.AsExpandable()
.Select(c => new
{
Childs = Enumerable.Select(
MyTable.VisibleChilds.Invoke(c, dbContext),
cc => Convert(cfg.ChildsConfig).Invoke(dbContext, cc))
});
where the Convert is building an expression like
p => new MyTableSelect {
Id = p.Id,
Name = p.Name
}
depending on the given values from the config (to only read needed data from database).
but I'm struggeling with the second parameter to be passed to the Select call as I need cc to be passed to the Convert-call.
I guess I need something like Expression.Lambda<Func<>> but I don't see it.
Expression.Lambda>(Expression.Invoke(Instance.Convert(cfg.ChildOrganizersFilterConfig), ContextParameter, theEntity));
I am not familiar with your use of Invoke but if you just want to run a 'Converter' in a fluent syntax for use in a Linq Expression I could show you an example of that. Say I have three POCO classes, one parent container, a child container, and a container I want to convert to.
public class POC
{
public int Id { get; set; }
public string Name { get; set; }
public POC(int id, string name)
{
Id = id;
Name = name;
}
}
public class ChildPOC
{
public int ParentId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public ChildPOC(int parentId, string firstName, string lastName)
{
ParentId = parentId;
FirstName = firstName;
LastName = lastName;
}
}
public class ChildPOCAlter
{
public int ParentId { get; set; }
public string Name { get; set; }
public ChildPOCAlter(string first, string last, int parentId)
{
ParentId = parentId;
Name = $"{first} {last}";
}
}
I could write a converter method to take ChildPOC to ChildPOCAlter like so:
public static Converter<ChildPOC, ChildPOCAlter> ChildPOCOAlter()
{
return new Converter<ChildPOC, ChildPOCAlter>((x) => { return new ChildPOCAlter(x.FirstName, x.LastName, x.ParentId); });
}
I could then populate some data:
var someParents = new List<POC> { new POC(1, "A"), new POC(2, "B") };
var somechildren = new List<ChildPOC> { new ChildPOC(1, "Brett", "x"), new ChildPOC(1, "Emily", "X"), new ChildPOC(2, "John", "Y") };
And then I may want to take these relationships and apply a converter directly on it:
var relationships = someParents.Select(x => new
{
Id = x.Id,
Name = x.Name,
Children = somechildren.Where(y => y.ParentId == x.Id).ToList().ConvertAll(ChildPOCOAlter())
});
I have the code below. I'd like to convert all items in this list to uppercase.
Is there a way to do this in Linq ?
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
public class MyClass
{
List<Person> myList = new List<Person>{
new Person { FirstName = "Aaa", LastName = "BBB", Age = 2 },
new Person{ FirstName = "Deé", LastName = "ève", Age = 3 }
};
}
Update
I don't want to loop or go field by field. Is there a way by reflection to uppercase the value for each property?
Why would you like to use LINQ?
Use List<T>.ForEach:
myList.ForEach(z =>
{
z.FirstName = z.FirstName.ToUpper();
z.LastName = z.LastName.ToUpper();
});
EDIT: no idea why you want to do this by reflection (I wouldn't do this personally...), but here's some code that'll uppercase all properties that return a string. Do note that it's far from being perfect, but it's a base for you in case you really want to use reflection...:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
public static class MyHelper
{
public static void UppercaseClassFields<T>(T theInstance)
{
if (theInstance == null)
{
throw new ArgumentNullException();
}
foreach (var property in theInstance.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
var theValue = property.GetValue(theInstance, null);
if (theValue is string)
{
property.SetValue(theInstance, ((string)theValue).ToUpper(), null);
}
}
}
public static void UppercaseClassFields<T>(IEnumerable<T> theInstance)
{
if (theInstance == null)
{
throw new ArgumentNullException();
}
foreach (var theItem in theInstance)
{
UppercaseClassFields(theItem);
}
}
}
public class Program
{
private static void Main(string[] args)
{
List<Person> myList = new List<Person>{
new Person { FirstName = "Aaa", LastName = "BBB", Age = 2 },
new Person{ FirstName = "Deé", LastName = "ève", Age = 3 }
};
MyHelper.UppercaseClassFields<Person>(myList);
Console.ReadLine();
}
}
LINQ does not provide any facilities to update underlying data. Using LINQ, you can create a new list from an existing one:
// I would say this is overkill since creates a new object instances and
// does ToList()
var updatedItems = myList.Select(p => new Person
{
FirstName = p.FirstName.ToUpper(),
LastName = p.LastName.ToUpper(),
Age = p.Age
})
.ToList();
If using LINQ is not principal, I would suggest using a foreach loop.
UPDATE:
Why you need such solution? Only one way of doing this in generic manner - reflection.
the Easiest approach will be to use ConvertAll:
myList = myList.ConvertAll(d => d.ToUpper());
Not too much different than ForEach loops the original list whereas ConvertAll creates a new one which you need to reassign.
var people = new List<Person> {
new Person { FirstName = "Aaa", LastName = "BBB", Age = 2 },
new Person{ FirstName = "Deé", LastName = "ève", Age = 3 }
};
people = people.ConvertAll(m => new Person
{
FirstName = m.FirstName?.ToUpper(),
LastName = m.LastName?.ToUpper(),
Age = m.Age
});
to answer your update
I don't want to loop or go field by field. Is there a way by
reflection to uppercase the value for each property?
if you don't want to loop or go field by field.
you could use property on the class to give you the Uppercase like so
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public string FirstNameUpperCase => FirstName.ToUpper();
public string LastNameUpperCase => LastName.ToUpper();
}
or you could use back field like so
public class Person
{
private string _firstName;
public string FirstName {
get => _firstName.ToUpper();
set => _firstName = value;
}
private string _lastName;
public string LastName {
get => _lastName.ToUpper();
set => _lastName = value;
}
public int Age { get; set; }
}
You can only really use linq to provide a list of new objects
var upperList = myList.Select(p=> new Person {
FirstName = (p.FirstName == null) ? null : p.FirstName.ToUpper(),
LastName = (p.LastName == null) ? null : p.LastName.ToUpper(),
Age = p.Age
}).ToList();
p.lastname.ToString().ToUpper().Contains(TextString)
My entities are like this:
class Address
{
public string Number { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string Country { get; set; }
}
class Person
{
public string Name { get; set; }
public int Age { get; set; }
public Address PostalAddress { get; set; }
}
Person newPerson =
new Person()
{
Name = "Kushan",
Age = 25,
PostalAddress =
new Address()
{
Number = "No 25",
Street = "Main Street",
City = "Matale",
Country = "Sri Lanka"
}
};
Now I wanna map this newPerson object into JSON object like this,
{
"PER_NAME" : "Kushan",
"PER_AGE" : "25",
"PER_ADDRESS" : {
"ADD_NUMBER" : "No 25",
"ADD_STREET" : "Main Street",
"ADD_CITY" : "Matale",
"ADD_COUNTRY" : "Sri Lanka"
}
}
Note: Above is just an example.
What I need is, I need to customize the Key at the serializing time. by default it is taking property name as the key. I can't change property names. How to do this?
Also, is it possible to change to order of appearing key-value pairs in JSON obj.?
You need to add DataContract attributes to your classes and DataMember to the properties. Set Name property of DataMemeber attribute to your custom property name and Order property to define the order.
[DataContract]
public class Person
{
[DataMember(Name = "PER_NAME", Order = 1)]
public string Name { get; set; }
[DataMember(Name = "PER_AGE", Order = 2)]
public int Age { get; set; }
[DataMember(Name = "PER_ADDRESS", Order = 3)]
public Address PostalAddress { get; set; }
}
Then you can do this:
var newPerson = new Person()
{
Name = "Kushan",
Age = 25,
PostalAddress = new Address()
{
Number = "No 25",
Street = "Main Street",
City = "Matale",
Country = "Sri Lanka"
}
};
MemoryStream stream = new MemoryStream();
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Person));
ser.WriteObject(stream, newPerson);
To check the result:
var result = Encoding.ASCII.GetString(stream.ToArray());
{"PER_NAME":"Kushan","PER_AGE":25,"PER_ADDRESS":{"ADD_NUMBER":"No 25","ADD_STREET":"Main Street","ADD_CITY":"Matale","ADD_COUNTRY":"Sri Lanka"}}
You can serialize an anonymous type with JavaScriptSerializer, so you might try projecting your object into the shape you want to serialize:
person.Select(s => new { PER_NAME = s.Name, PER_AGE = s.Age });