c# – 如何通过webapi2将扁平列表返回到breezejs?

我一直在努力这一周.我在DB中有一个人员和公司的表.但是,还有一个公司表的CompanyPerson,它有一些额外的属性,如IsPrimaryPerson.大.如果我将每件东西加载到breezejs中,那就可以工作了.

所以问题在于我想创建一个人员列表,但是像公司一样扁平化,例如左外连接,这样我也可以让每个人和公司在一条线上,也包括那些没有公司的人.

这个在C#中的linq语句给了我那个列表,我使用linqPad来实现它.这是一个左外连接sql的对等.

  from p in Person
    join cp in CompanyPerson
     on p.Id equals cp.PersonId
     into companyPersonGroups
     from cp in companyPersonGroups.DefaultIfEmpty()
    select new {
        Person = p,
        CompanyPerson = cp,
        Company = cp.Company
        }

大.但是我不知道的是,如何通过webapi2将这样的列表返回到breezejs.问题一是linq返回一个匿名对象.我尝试创建类似于ContactPerson对象并具有Person和Company的属性,但我不知道如何回到微风,因为它不是元数据的一部分.

控制器,这取决于我尝试和做的各种原因.从“实体或复杂类型’SiteTrackerModel.ContactPerson’不能在LINQ to Entities查询中构造”到其他问题.只是在这里向你展示我正在尝试的方式.

    [BreezeQueryable(MaxExpansionDepth = 3)]
    [HttpGet]
    public IQueryable<ContactPerson> PersonsFlattened()
    {
        //return _contextProvider.QueryAll<Person>();

        var contacts = from person in _contextProvider.QueryAll<Person>()
                       join companyPerson in CompanyPersons() on person.Id equals companyPerson.PersonId into companyPersonGroups
                       from companyPerson in companyPersonGroups.DefaultIfEmpty()
                       select new ContactPerson()
                       {
                           FirstName = person.FirstName,
                           IsPrimaryPerson = companyPerson.IsPrimaryPerson,
                           CompanyName = companyPerson.Company.Name
                       };

        return contacts;

    }

BreezeJs呼叫Angular

return EntityQuery.from("PersonsFlattened")
                 //.toType("ContactPerson")
                 .orderBy(orderBy)
                 .using(self.manager).execute()
                 .then(querySucceeded, self._queryFailed);

这是我试图压扁并回归微风的类/表.我已经削减了大部分属性

Person.cs(Edmx / db中的人员表)

public partial class Person
{
    public Person()
    {
        this.Companies = new HashSet<CompanyPerson>();
    }

    public int Id { get; set; }
    public string UserName { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public virtual ICollection<CompanyPerson> Companies { get; set; }
}

CompanyPerson.cs(Edmx / db中的CompanyPerson表)

public partial class CompanyPerson
{
    public int PersonId { get; set; }
    public int CompanyId { get; set; }
    public bool IsPrimaryPerson { get; set; }

    public virtual Company Company { get; set; }
    public virtual Person Person { get; set; }
}

Company.cs(edmx / db中的公司表)

public partial class Company
{
    public Company()
    {
        this.Projects = new HashSet<Project>();
        this.PhoneNumbers = new HashSet<CompanyPhoneNumber>();
        this.Addresses = new HashSet<CompanyAddress>();
        this.Persons = new HashSet<CompanyPerson>();
    }

    public int Id { get; set; }
    public string Name { get; set; }

    public virtual ICollection<CompanyPerson> Persons { get; set; }
}

我甚至尝试在sql中创建一个给我数据的视图,但我不能让Breezejs弄清楚它是什么,但这只是上述目标的一种方法.即使没有公司,人员和公司也会被列为扁平化列表.

最佳答案 您可以将投影数据发送到BreezeJS并将它们转换为您在客户端上定义的自定义EntityType.您不能指望ContactPerson类型显示在Entity Framework生成的服务器的元数据中;它是一个DTO,而不是EF所知道的模型的一部分.

这不应该阻止你在Breeze客户端上定义ContactPerson.了解如何在文档中使用create client-side metadata.

It’s worth noting that you do not have to define all of your metadata on the client to take advantage of this feature. Just add this ContactPerson type.

下一个技巧是让BreezeJS意识到您的投影数据应该转换为客户端上的ContactPerson实体.

默认情况下,Breeze无法识别匿名类型数据.您可以为toType query clause提供一些帮助.在客户端元数据中定义类型后,可以在查询中取消注释该子句.

return EntityQuery.from("PersonsFlattened")
       .toType("ContactPerson") // Should work after defining ContactPerson on client
       .orderBy(orderBy)
       .using(self.manager).execute()
       .then(querySucceeded, self._queryFailed);

如果您投影到服务器端的ContactPerson类型并连接“PersonsFlattened”端点和元数据中的自定义客户端ContactPerson类型之间的点,则不需要toType子句.我想我会重命名该端点“ContactPersons”以保持一致性.

N.B.:我相信你意识到你已经定义了只读类型. Breeze不知道如此,如果您在BreezeJS中对ContactPerson实体进行更改,管理器将尝试保存它.您的保存尝试将抛出服务器,除非您捕获传入的更改并使用它做一些了不起的事情,可能是在BeforeSaveEntity方法中.

点赞