我已经为此苦苦挣扎了一个星期。我在数据库中有一个 Person 和 Company 表。但是,还有一个 CompanyPerson 的连接表,它具有一些额外的属性,例如 IsPrimaryPerson。伟大的。如果我将每个东西都单独加载到 Breeze 中,那么工作和所有这些东西。
所以问题是我想创建一个人员列表,但与公司一起扁平化,就像一个左外连接,这样我也将每个人和公司放在一条线上,还包括那些没有公司的人。
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 的属性,但我不知道如何重新开始,因为它不是元数据的一部分。
Controller ,由于各种原因,这不起作用,具体取决于我尝试和执行的操作。从“无法在 LINQ to Entities 查询中构造实体或复杂类型‘SiteTrackerModel.ContactPerson’”到其他问题。把它放在这里,以某种方式向你展示我正在尝试的东西。
[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);
这是我试图压平并恢复 Breeze 的类(class)/表格。我已经削减了大部分属性
Person.cs(Edmx/db 中的 Person 表)
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 中创建一个给我数据的 View ,但我无法让 Breezejs 弄清楚它是什么,但这只是实现上述目标的一种手段。扁平化的人员和公司列表,即使他们没有公司。
最佳答案
您可以将投影数据发送到 BreezeJS 并将它们转换为您在客户端定义的自定义 EntityType
。您不能期望 ContactPerson
类型出现在 Entity Framework 生成的服务器的元数据中;它是一个 DTO,而不是 EF 知道的模型的一部分。
这不应阻止您在 Breeze 客户端上定义 ContactPerson
。在文档中了解如何 create client-side metadata。
下一个技巧是让 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
方法中。关于c# - 如何通过 webapi2 将扁平列表返回给 Breeze js?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24441138/