如何通过webapi2将一个扁平的列表返回给breezejs
本文关键字:列表 返回 breezejs 一个 webapi2 何通过 | 更新日期: 2023-09-27 18:10:31
我已经为此挣扎了一个星期了。我在DB中有一个Person和Company的表。然而,也有一个joiner Table CompanyPerson,它有一些额外的属性,如IsPrimaryPerson。太好了。工作和所有的东西,如果我把每个东西自己加载到breezejs。
所以问题是,我想创建一个Persons列表,但是用Companies平面化,就像左外连接一样,这样我也可以将每个人和公司放在一行上,还包括那些没有公司的人。
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对象和有属性的人和公司,但我不知道如何回到微风,因为它不是元数据的一部分。
控制器,这不起作用的各种原因取决于我尝试做什么。来自"实体或复杂类型"SiteTrackerModel。ContactPerson'不能在LINQ到实体查询中构造',以解决其他问题。我把它放在这里,让你看看我在做什么。
[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;
}
Angular中的BreezeJs调用
return EntityQuery.from("PersonsFlattened")
//.toType("ContactPerson")
.orderBy(orderBy)
.using(self.manager).execute()
.then(querySucceeded, self._queryFailed);
这里是类/表,我试图平,并返回到微风。我已经删减了大部分属性
Person.cs (Person Table in 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 (CompanyPerson Table in Edmx/db)
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 (Company Table in 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
类型显示在元数据从服务器已由实体框架生成;这是一个DTO,而不是EF所知道的模型的一部分。
这不应该阻止您在您的Breeze客户端上定义ContactPerson
。了解如何在文档中创建客户端元数据。
值得注意的是,不必在客户端上定义所有元数据来利用此特性。只要添加这个ContactPerson
类型。
下一个技巧是让BreezeJS意识到你的投影数据应该在客户端转换为ContactPerson
实体。
默认情况下,Breeze不会识别匿名类型数据。您可以使用 如果您投射到服务器端 注意::我相信您已经意识到您已经定义了只读类型。Breeze不知道这一点,所以如果你在BreezeJS中更改了toType
查询子句为它提供一些帮助。在客户端元数据中定义了类型之后,可以取消查询中的该子句的注释。return EntityQuery.from("PersonsFlattened")
.toType("ContactPerson") // Should work after defining ContactPerson on client
.orderBy(orderBy)
.using(self.manager).execute()
.then(querySucceeded, self._queryFailed);
ContactPerson
类型,并将"personsflat"端点与元数据中自定义的客户端ContactPerson
类型之间的点连接起来,则不需要toType
子句。为了保持一致性,我想我应该将端点重命名为"ContactPersons"。ContactPerson
实体,管理员将尝试保存它。您的保存尝试将在服务器上抛出,除非您捕捉到传入的更改并对它做一些了不起的事情,也许是在BeforeSaveEntity
方法中。
例外"实体或复杂类型" SiteTrackerModel。与类ContactPerson
的声明方式有关。LINQ到实体只能构造一个数据传输对象:类,该类只包含带有普通getter和setter的公共属性,没有构造函数。
检查ContactPerson
类定义