【问题标题】:c# how to populate a complex object containing a list with sqlc#如何用sql填充包含列表的复杂对象
【发布时间】:2014-03-31 08:14:30
【问题描述】:

我目前有一个使用实体框架的对象模型,其中包含一个具有列表属性的复杂对象。我使用此处提出的第二个选项将其存储在数据库中:Representing a list in a SQL database

但总结一下:

Person()
{
  long Id;//primary key
  string Name;
  List<long> ResponsibleFor; //list of id    
}

存储为以下 2 个表格

Persons:
 Id,
 Name

Responsibilities:
 Id,
 PersonId,
 ResponsibleForId

现在我有点不知道如何重新填充 Person 对象。我目前的方法如下:

 from p in db.Persons
 join r in db.Responsibilities on p.Id equals r.PersonId
 where p.Id == IdImSearchingFor
 select new Person
 {
  Id = p.Id
  ResponsibileFor = ?
 }

我一直在尝试重新填充该 List 属性。

有什么建议吗?

谢谢!

【问题讨论】:

    标签: c# sql list object join


    【解决方案1】:

    你需要对加入的结果进行分组,让所有人负责。

    试试

    var result = from p in db.Persons
                 join r in db.Responsibilities on p.Id equals r.PersonId
                 where p.Id == IdImSearchingFor
                 group r.ResponsibleForId by p into g
                 select new Person 
                 {
                     Id = g.Key.Id, 
                     Name = g.Key.Name,
                     ResponsibleFor = g.ToList()
                 };
    

    【讨论】:

    • 这可能有效,但分组到 g 似乎会丢失 Person 的其他元素(例如名称,但实际上不止于此)。有没有办法进行不同的分组,以便我可以获取 p 的所有元素,然后从 r 中获取列表?
    • @Norrec 您也可以使用 dbPersons 中的整个对象作为 Key 进行分组,然后使用它的属性。我编辑了我的答案。
    • 我最终在我的解决方案上实施了你的解决方案,因为它更干净。谢谢!
    【解决方案2】:

    假设您想获取 ID 为 1 的人员..

    from p in db.Persons
     join r in db.Responsibilities on p.Id equals r.PersonId
     where p.Id == 1
     select new Person
     {
      Id = p.Id
      ResponsibileFor = p.ReponsibleFor 
    }
    

    【讨论】:

    • 这会起作用,除非我使用的是 EF,并且 p.ResponsibleFor 是自动生成的类型 而不是
    【解决方案3】:

    看看这个。我已经测试过它是普通的类和列表,而不是 EF 或任何其他 ORM。

    以下是我理解的类结构

    class Person
    {
        public long Id;//primary key
        public string Name;
    }
    
    class Responsibility
    {
        public long Id;//primary key
        public long PersonId;
        public long ResponsibleForId; 
    }
    

    以下是2个测试列表

    List<Person> Persons = new List<Person>() { new Person() { Id = 1, Name = "Samar" } };
    List<Responsibility> Responsibilities = new List<Responsibility>() { new Responsibility() { Id = 1, PersonId = 1, ResponsibleForId = 1 }, new Responsibility() { Id = 2, PersonId = 1, ResponsibleForId = 2 } };
    

    以下是查询

    var allPeople = from p in Persons
                    join r in Responsibilities on p.Id equals r.PersonId into g
                    where p.Id == 1
                    select new
                    {
                        Id = p.Id,
                        ReponsibleFor = g.Select(x => x.ResponsibleForId).ToList()
                    };
    

    希望这是您正在寻找的。​​p>

    【讨论】:

    • 由于某种原因,这个 g.Select(x => x.ResponsibleForId).ToList() 抛出异常:“无法使用'System.Data.Entity.Infrastructure.ObjectReferenceEqualityComparer'类型的表达式对于“System.Collections.Generic.IEqualityComparer`1[System.Int64]”类型的构造函数参数”
    【解决方案4】:

    虽然每个人之前的回答都对我有所帮助(谢谢!),但他们并没有完全发挥作用。所以我想我应该在这里添加我的解决方案,即使用连接、分组和嵌套选择的组合。

    from p in db.Persons
    where p.Id == IdImSearchingFor
    join r in db.Responsibilities on p.Id equals r.ParentId into pr
    select new Person
    {
        Id = p.Id,
        name = p.Name,
        ResponsibleFor = ( from a in pr
                           where a.ParentId == IdImSearchingFor
                           select new Person
                           {
                               Id = a.Id
                           }).ToList<Person>()
    }
    

    【讨论】:

      【解决方案5】:

      我的建议是使用延迟加载模式来获取您的列表,它可能会更好地执行和扩展。用你的例子。

      public class Person()
      {
        public long Id { get; set; }
        public string Name { get; set;}
        private Lazy<List<long>> _responsibleFor;
        public List<long> ResponsibleFor
        {
          get { return _responsibleFor.Value; }
        }
      
        public void SetResponsibleFor(Func<long, List<long>> getResponsibleFor)
        {
          _responsibleFor = new Lazy<List<long>>( () => getResponsibleFor(Id) );
        }
      
        public Person():base() { }
        public Person(long id, string name)
        {
          Id = id;
          Name = name
        }
      
      }
      
         // Implementation
         var p = new Person(1,"John Doe");
         p.SetResponsibleFor(GetResponsibleForPerson); //Pass a function/method which takes the long for input parameter and outputs List<long>
      

      【讨论】:

        猜你喜欢
        • 2020-09-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多