LINQ to Entities - 根据连接、条件和排序获取结果
LINQ to Entities - Get results based on join, conditions and sorting
我有一些代码循环遍历 3 个单独列表的记录并执行创建新对象的逻辑。它有效,但需要很长时间。我希望我可以将其全部简化为 LINQ to Entities 查询。
基本上,我有一个人员列表和一个 Phone 数字列表。 Phone 数字具有类型('cell'、'home'、'office' 等)和等级 (1-x)。如果某人有两个单元格 phones,则排名较低的优先。
结果集应该只有一个单元格(排名最低)和一个家phone(排名最低)。如果没有单元格或家 phone.
,这些应该为空
Person person1 = new("Person", "One");
Person person2 = new("Person", "Two");
Person person3 = new("Person", "Three");
Person person4 = new("Person", "Four");
Person person5 = new("Person", "Five");
Phone ph1 = new("1112222222", "home", 2, person1);
Phone ph2 = new("1111111111", "cell", 1, person1);
Phone ph3 = new("2223331111", "cell", 1, person2);
Phone ph4 = new("3334441111", "cell", 1, person3);
Phone ph5 = new("3335552222", "cell", 2, person3);
Phone ph6 = new("4446662222", "home", 2, person4);
Phone ph7 = new("5557772222", "cell", 3, person5);
Phone ph8 = new("5557773333", "home", 2, person5);
// Create two lists.
List<Person> people = new() { person1, person2, person3, person4, person5 };
List<Phone> phones = new() { ph1, ph2, ph3, ph4, ph5, ph6, ph7, ph8 };
***//CAN A LINQ to ENTITIES QUERY PRODUCE THE DESIRED RESULTS
var query =
from person in people
join ph in phones on person equals ph.Owner into persPh
from personPhones in persPh.DefaultIfEmpty()
select new PersonPhone
{
FirstName = person.FirstName,
LastName = person.LastName,
CellPhoneNumber = personPhones?.Number ?? string.Empty, //<==== Needs to be lowest ranking number of type = "cell"
HomePhoneNumber = personPhones?.Number ?? string.Empty //<==== Needs to be lowest ranking number of type = "home"
};***
foreach (PersonPhone v in query)
{
Console.WriteLine($"{v.FirstName + " " + v.LastName + ":",-15} {v.CellPhoneNumber,-15} {v.HomePhoneNumber,-15} ");
}
// This code Should produce the following output:
//
// Person One: 1111111111 1112222222
// Person Two: 2223331111
// Person Three: 3334441111
// Person Four: 4446662222
// Person Five: 5557772222 5557773333
public record class Person(string FirstName, string LastName);
public record class Phone(string Number, string Type, int Rank, Person Owner);
public record class PersonPhone(string FirstName, string LastName, string CellPhoneNumber, string HomePhoneNumber);
尝试使用 linq。我给了你 2 个使用 Linqpad 的教育选项
void Main()
{
Person person1 = new("Person", "One");
Person person2 = new("Person", "Two");
Person person3 = new("Person", "Three");
Person person4 = new("Person", "Four");
Person person5 = new("Person", "Five");
Phone ph1 = new("1112222222", "home", 2, person1);
Phone ph2 = new("1111111111", "cell", 1, person1);
Phone ph3 = new("2223331111", "cell", 1, person2);
Phone ph4 = new("3334441111", "cell", 1, person3);
Phone ph5 = new("3335552222", "cell", 2, person3);
Phone ph6 = new("4446662222", "home", 2, person4);
Phone ph7 = new("5557772222", "cell", 3, person5);
Phone ph8 = new("5557773333", "home", 2, person5);
// Create two lists.
List<Person> people = new() { person1, person2, person3, person4, person5 };
List<Phone> phones = new() { ph1, ph2, ph3, ph4, ph5, ph6, ph7, ph8 };
var personPhoneList = new List<PersonPhone>();
//option 1
people.ForEach(person =>
{
var pp = new PersonPhone()
{
FirstName = person.FirstName,
LastName = person.LastName,
CellPhoneNumber = phones.FirstOrDefault(cp => cp.type == "cell" && cp.Owner == person)?.Number,
HomePhoneNumber = phones.FirstOrDefault(cp => cp.type == "home" && cp.Owner == person)?.Number
};
personPhoneList.Add(pp);
});
personPhoneList.Select(v => new
{
v.FirstName,
v.LastName,
v.CellPhoneNumber,
v.HomePhoneNumber
}).Dump("Option 1");
//option 2
people.Select(person => new PersonPhone()
{
FirstName = person.FirstName,
LastName = person.LastName,
CellPhoneNumber = phones.OrderBy(o=> o.Rank).FirstOrDefault(cp => cp.type == "cell" && cp.Owner == person)?.Number,
HomePhoneNumber = phones.OrderBy(o=> o.Rank).FirstOrDefault(cp => cp.type == "home" && cp.Owner == person)?.Number
})
.ToList().Dump("option 2");
}
public class PersonPhone
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string CellPhoneNumber { get; set; }
public string HomePhoneNumber { get; set; }
}
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Person(string _first, string _last)
{
FirstName = _first;
LastName = _last;
}
}
public class Phone
{
public string Number { get; set; }
public string type { get; set; }
public int Rank { get; set; }
public Person Owner { get; set; }
public Phone(string _number, string _type, int _order, Person _person)
{
Number = _number;
type = _type;
Rank = _order;
Owner = _person;
}
}
我有一些代码循环遍历 3 个单独列表的记录并执行创建新对象的逻辑。它有效,但需要很长时间。我希望我可以将其全部简化为 LINQ to Entities 查询。
基本上,我有一个人员列表和一个 Phone 数字列表。 Phone 数字具有类型('cell'、'home'、'office' 等)和等级 (1-x)。如果某人有两个单元格 phones,则排名较低的优先。
结果集应该只有一个单元格(排名最低)和一个家phone(排名最低)。如果没有单元格或家 phone.
,这些应该为空Person person1 = new("Person", "One");
Person person2 = new("Person", "Two");
Person person3 = new("Person", "Three");
Person person4 = new("Person", "Four");
Person person5 = new("Person", "Five");
Phone ph1 = new("1112222222", "home", 2, person1);
Phone ph2 = new("1111111111", "cell", 1, person1);
Phone ph3 = new("2223331111", "cell", 1, person2);
Phone ph4 = new("3334441111", "cell", 1, person3);
Phone ph5 = new("3335552222", "cell", 2, person3);
Phone ph6 = new("4446662222", "home", 2, person4);
Phone ph7 = new("5557772222", "cell", 3, person5);
Phone ph8 = new("5557773333", "home", 2, person5);
// Create two lists.
List<Person> people = new() { person1, person2, person3, person4, person5 };
List<Phone> phones = new() { ph1, ph2, ph3, ph4, ph5, ph6, ph7, ph8 };
***//CAN A LINQ to ENTITIES QUERY PRODUCE THE DESIRED RESULTS
var query =
from person in people
join ph in phones on person equals ph.Owner into persPh
from personPhones in persPh.DefaultIfEmpty()
select new PersonPhone
{
FirstName = person.FirstName,
LastName = person.LastName,
CellPhoneNumber = personPhones?.Number ?? string.Empty, //<==== Needs to be lowest ranking number of type = "cell"
HomePhoneNumber = personPhones?.Number ?? string.Empty //<==== Needs to be lowest ranking number of type = "home"
};***
foreach (PersonPhone v in query)
{
Console.WriteLine($"{v.FirstName + " " + v.LastName + ":",-15} {v.CellPhoneNumber,-15} {v.HomePhoneNumber,-15} ");
}
// This code Should produce the following output:
//
// Person One: 1111111111 1112222222
// Person Two: 2223331111
// Person Three: 3334441111
// Person Four: 4446662222
// Person Five: 5557772222 5557773333
public record class Person(string FirstName, string LastName);
public record class Phone(string Number, string Type, int Rank, Person Owner);
public record class PersonPhone(string FirstName, string LastName, string CellPhoneNumber, string HomePhoneNumber);
尝试使用 linq。我给了你 2 个使用 Linqpad 的教育选项
void Main()
{
Person person1 = new("Person", "One");
Person person2 = new("Person", "Two");
Person person3 = new("Person", "Three");
Person person4 = new("Person", "Four");
Person person5 = new("Person", "Five");
Phone ph1 = new("1112222222", "home", 2, person1);
Phone ph2 = new("1111111111", "cell", 1, person1);
Phone ph3 = new("2223331111", "cell", 1, person2);
Phone ph4 = new("3334441111", "cell", 1, person3);
Phone ph5 = new("3335552222", "cell", 2, person3);
Phone ph6 = new("4446662222", "home", 2, person4);
Phone ph7 = new("5557772222", "cell", 3, person5);
Phone ph8 = new("5557773333", "home", 2, person5);
// Create two lists.
List<Person> people = new() { person1, person2, person3, person4, person5 };
List<Phone> phones = new() { ph1, ph2, ph3, ph4, ph5, ph6, ph7, ph8 };
var personPhoneList = new List<PersonPhone>();
//option 1
people.ForEach(person =>
{
var pp = new PersonPhone()
{
FirstName = person.FirstName,
LastName = person.LastName,
CellPhoneNumber = phones.FirstOrDefault(cp => cp.type == "cell" && cp.Owner == person)?.Number,
HomePhoneNumber = phones.FirstOrDefault(cp => cp.type == "home" && cp.Owner == person)?.Number
};
personPhoneList.Add(pp);
});
personPhoneList.Select(v => new
{
v.FirstName,
v.LastName,
v.CellPhoneNumber,
v.HomePhoneNumber
}).Dump("Option 1");
//option 2
people.Select(person => new PersonPhone()
{
FirstName = person.FirstName,
LastName = person.LastName,
CellPhoneNumber = phones.OrderBy(o=> o.Rank).FirstOrDefault(cp => cp.type == "cell" && cp.Owner == person)?.Number,
HomePhoneNumber = phones.OrderBy(o=> o.Rank).FirstOrDefault(cp => cp.type == "home" && cp.Owner == person)?.Number
})
.ToList().Dump("option 2");
}
public class PersonPhone
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string CellPhoneNumber { get; set; }
public string HomePhoneNumber { get; set; }
}
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Person(string _first, string _last)
{
FirstName = _first;
LastName = _last;
}
}
public class Phone
{
public string Number { get; set; }
public string type { get; set; }
public int Rank { get; set; }
public Person Owner { get; set; }
public Phone(string _number, string _type, int _order, Person _person)
{
Number = _number;
type = _type;
Rank = _order;
Owner = _person;
}
}