这是我的问题:我有一个由员工和学生实施的IPerson。我真正想要的是你在下面看到的。一个LINQ语句来获取每种类型的IPerson。这很有效,直到我调用方法;)。关于为什么我会收到错误是有道理的,但我真的很难找到一个合适的方法从数据库中提取所有IPerson对象并避免将switch语句放在我的应用程序中。
public IQueryable<IPerson> getPersons() {
// gives Types in Union or Concat have different members assigned error
var people = from p in db.Persons select p;
var students = (from s in people
where s.TypeId == (int)PersonType.Student
select new Student
{
Id = s.Id,
Age = s.Age.GetValueOrDefault(0),
Name = s.Name,
Major = s.Student.Major ?? "None",
CreditHours = s.Student.CreditHours.GetValueOrDefault(0),
PersonType = (PersonType)s.TypeId
}).Cast<IPerson>();
var employees = (from e in people
where e.TypeId == (int)PersonType.Employee
select new Employee
{
Id = e.Id,
Age = e.Age.GetValueOrDefault(0),
Name = e.Name,
PersonType = (PersonType)e.TypeId,
Salary = e.Employee.Salary.GetValueOrDefault(0)
}).Cast<IPerson>();
return students.Concat<IPerson>(employees);
//return (students.ToList()).Concat<IPerson>(employees.Cast<IPerson>().ToList()).AsQueryable<IPerson>();
}
上面,有一个注释掉的return语句 - 基本上是一个.ToList()并且放弃了整个延迟执行的事情,创建了2个SQL语句 - 并不理想。
感谢任何帮助!
答案 0 :(得分:2)
这个怎么样:
public IQueryable<IPerson> getPersons() {
// gives Types in Union or Concat have different members assigned error
var people = from p in db.Persons select p;
return (from s in people
where s.TypeId == (int)PersonType.Student
select new Student
{
Id = s.Id,
Age = s.Age.GetValueOrDefault(0),
Name = s.Name,
Major = s.Student.Major ?? "None",
CreditHours = s.Student.CreditHours.GetValueOrDefault(0),
PersonType = (PersonType)s.TypeId
}).Cast<IPerson>().Union((from e in people
where e.TypeId == (int)PersonType.Employee
select new Employee
{
Id = e.Id,
Age = e.Age.GetValueOrDefault(0),
Name = e.Name,
PersonType = (PersonType)e.TypeId,
Salary = e.Employee.Salary.GetValueOrDefault(0)
}).Cast<IPerson>());
}
它并没有好多少,但是你可以在一次通话中得到它。或者,我会做的是这样的事情:
public IPerson GetPerson(Person p) //I'm guessing that the objects in collection db.Persons is of type Person
{
IPerson ret;
switch(p.TypeId)
{
case (int)PersonType.Student: ret = .......break;
case (int)PersonType.Employee: ret = ......break;
}
return ret;
}
public IQueryable<IPerson> getPersons() {
return (from p in db.Persons select p).ToList().Select(p => GetPerson(p)).AsQueryable();
}
但是你又得到了switch语句。另外,如果您不喜欢在DB上执行ToList()(如果我没记错LinqToSQL不支持使用带变量的构造函数的函数),您可以尝试添加方法GetPerson(我可能会重命名)由LinqToSQL(部分类)生成的Person类,但我不确定这是否合法。
但是我不知道如何在不使用开关的情况下使用来自getPersons的IQueryable,我不知道。
答案 1 :(得分:0)
这是我最终做的事情:
存储库
public IQueryable<Database.Person> getDbPersons() {
return from p in db.Persons select p;
}
// Called by Service layer when viewing all People
public IQueryable<Person> getPersons() {
return from p in getDbPersons() select new Person { //yada yada };
}
服务层
public IList<Person> getPersons() {
return from p in repository.getPersons() return p;
}
public IPerson getPerson(int id) {
return repository.getDbPersons().withPersonId(id);
}
// Person Filter Class
public static class PersonFilters
{
public static IPerson WithPersonId(this IQueryable<SqlServer.Person> qry, int Id)
{
return (from p in qry
where p.Id == Id
select p).Select(p => ThisPerson(p)).SingleOrDefault();
}
private static IPerson ThisPerson(OneToOne.Data.SqlServer.Person x)
{
IPerson ret;
switch (x.TypeId)
{
case (int)PersonType.Employee:
var e = new Employee();
e.Id = x.Id;
e.Name = x.Name;
e.Age = x.Age.GetValueOrDefault(0);
e.Salary = x.Employee.Salary.GetValueOrDefault(0);
e.PersonType = PersonType.Employee;
ret = e;
break;
case (int)PersonType.Student:
var s = new Student();
s.Id = x.Id;
s.Name = x.Name;
s.Age = x.Age.GetValueOrDefault(0);
s.Major = x.Student.Major;
s.PersonType = PersonType.Employee;
ret = s;
break;
default:
throw new Exception("Bad Person Type");
}
return ret;
}
}
再次感谢,Alxandr指出我正确的方向!