我使用数据库优先的方法。我的数据库中有以下表格:
[Country](ID, Name)
[Status](ID, Name)
[User](ID, Name)
[Object](ID, StatusID, Name)
[ObjectXCountries](ObjectID, CountryID)
[ObjectXUser](ObjectID, UserID)
现在实体框架创建这些实体:
Country { ID, Name }
User { ID, Name }
Status { ID, Name }
Object { ID, StatusID, Status, Name, Countries, Users }
要编辑对象列表,UI需要以下JSON结构:
{
cnt: [ { id: 1, name: 'some country', ...}, ],
usr: [ { id: 1, name: 'some user', ...}, ],
st: [ { id: 1, name: 'some status', ...}, ],
objects: [ { id: 1, name: 'some name', st: 1, cnt: [ 1, 2, 3 ], usr: [ 1, 2, 3] }, ... ]
}
获取国家/地区、用户和状态的列表很简单,但如何获取与之相连的ID的对象列表?现在我有以下代码,这导致了一个非常低效的查询:
ctx.Object.Select(rec => new ObjectDTO {
ID = rec.ID,
Name = rec.Name,
StatusID = rec.StatusID,
UserIDs = rec.Users.Select(usr => usr.ID).ToArray(),
CountryIDs = rec.Countries.Select(cnt => cnt.ID).ToArray()
});
它转换为sql,这取决于对象的数量,它选择所有对象,然后为每个对象创建一个选择查询,以获得用户ID和国家/地区的列表。如果我有一百个对象,它将导致101个查询。第一个获取对象列表,第100个获取连接的id。(UPD:201个查询,每个实体都有两个额外的查询来获取用户ID和国家ID)。
是否可以只使用3个选择查询来选择此信息?在sql中很容易做到,但我想知道如何在实体框架中做到这一点。
UPD:在SQL中,我只需要写3个select语句:
SELECT * FROM [Object]
SELECT * FROM [ObjectXCountries]
SELECT * FROM [ObjectXUser]
从代码中调用此查询,然后连接ObjectID上的三个结果集。也许有某种方法可以使表[ObjectXCountries]和[ObjectXUser]在实体上下文中可用,这样我就可以编写类似的代码了?
UPD:我使用实体框架6.2。
好吧,在谷歌上搜索了很多并尝试了不同的方法之后,我找到了一个简单有效的解决方案。
多个查询是懒惰加载的结果。如果我"包含"我的导航属性,它将在一个查询中获得所有内容。这可以通过以下代码实现:
ctx
.Object
.Include("Users")
.Include("Countries")
.Select(rec => new ObjectDTO {
ID = rec.ID,
Name = rec.Name,
StatusID = rec.StatusID,
UserIDs = rec.Users.Select(usr => usr.ID).ToArray(),
CountryIDs = rec.Countries.Select(cnt => cnt.ID).ToArray()
});