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

时间:2014-06-26 22:18:09

标签: c# linq entity-framework breeze asp.net-web-api2

我一直在为此奋斗一周。我在数据库中有一个公司的表格。但是,还有一个 CompanyPerson 的木匠表,它有一些额外的属性,如 IsPrimaryPerson 。大。如果我将每件东西加载到breezejs中,那就可以工作了。

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

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

  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 Call in 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知道它是什么,但这只是实现上述目标的一种手段。一个扁平的人员和公司名单,即使他们没有公司。

2 个答案:

答案 0 :(得分:2)

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

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

  

值得注意的是,您无需在客户端上定义所有元数据以利用此功能。只需添加此ContactPerson类型。

下一个技巧是让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);

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

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

答案 1 :(得分:0)

例外&#34;实体或复杂类型&#39; SiteTrackerModel.ContactPerson&#39;不能在LINQ to Entities查询中构造&#34; 与如何声明类ContactPerson有关。 LINQ to entity只能构造pur Data Transfert Object :类,它只包含具有普通getter和setter且没有构造函数的公共属性。

检查ContactPerson班级定义。