选择项目并使用linq to SQL设置未映射的属性

时间:2017-06-28 06:08:12

标签: c# sql-server entity-framework linq

考虑我的数据库中的以下POCO:

public class Person
{
    [Key]
    public Int32 PersonId { get; set; }

    public String Name { get; set; }

    public Collection<Pet> Pets { get; set; }

    [NotMapped]
    public Int32 NumberOfPets { get; set; }
}

public class Pet
{
    [Key]
    public Int32 PetId { get; set; }

    public Int32 PersonId { get; set; }

    public Person Person { get; set; }

    public String Name { get; set; }
}

我想从我的存储库中获取People时设置NumberOfPets属性,但我不想隐含地一直加入Pets。

public class PersonRepository
{
    public IList<Person> GetAllPeople1()
    {
        return _context.People.Select(x => { x.NumberOfPets = x.Pets.Count(); return x; } ).ToList();
    }
    public IList<Person> GetAllPeople2()
    {
        return _context.People.Select(x => new Person
        {
            NumberOfPets = x.Pets.Count(),
            Name = x.Name
        }).ToList();
    }
    public IList<Person> GetAllPeople3()
    {
        var people = _context.People;
        foreach (var p in people)
        {
            p.NumberOfPets = p.Pets.Count();
        }
        return people.ToList();
    }
}

方法1有效,但不适用于Linq to SQL。 #2有效,但由于向Person添加了更多属性,因此很容易忘记在此处添加它。 #3将生成一大堆查询。我知道如何使用钱包SQL来实现这一目标,但不知道如何让EF以高效的方式为我工作。

是否有一种语法可以在生成(半)高效查询时使#1工作?

1 个答案:

答案 0 :(得分:1)

我不相信有比#2更好的方法(但正如你所提到的,它有自己的问题)。

一些替代方案:

  1. 编写一个代表您所追踪数据的视图。查询视图而不是直接针对Person
  2. 利用延迟加载。将NumberOfPets实施为:
  3. public int NumberOfPets { get { return Pets.Count(); } }
    

    此处,NumberOfPets只会在访问时查询宠物表。如果你愿意的话,你也可以加入一些缓存。