我一直在为此奋斗一周。我在数据库中有一个人和公司的表格。但是,还有一个 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知道它是什么,但这只是实现上述目标的一种手段。一个扁平的人员和公司名单,即使他们没有公司。
答案 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
班级定义。