英文:
Entity with List in Select statement
问题
开始考虑以下可能不可行,由于逻辑中存在错误和缺乏支持证据,但想要确认。
我们使用 LINQ 构建实体 SQL 语句,但需要在 Select 语句中使用 List 收集额外的数据。这些数据来自应用程序内存中先前的实体集合。直接使用 Entity 进行相同操作时没有问题。
伪代码如下:
List<ParticipationStatus> lstStatuses = GetStatuses();
var data = (
from user in dbContext.User
where user.JoinDate >= *date*
select new CustomObject
{
Name = user.FullName,
ParticipationStatus = lstStatuses
.Where(m => m.ParticipationStatusID == user.ParticipationStatusID)
.Select(x => x.Label)
.FirstOrDefault() + " Some string here"
} )
.ToList();
英文:
Beginning to think the below is not possible due to errors and lack of supporting evidence in logic but wanted to confirm.
We're using LINQ to build an entity SQL statement but need to use a List in the Select statement to gather additional data. This data is from a previous Entity collection in app memory. Doing the same thing straight up with Entity works without issue.
The pseudo-code looks like:
List<ParticipationStatus> lstStatuses = GetStatuses();
var data = (
from user in dbContext.User
where user.JoinDate >= *date*
select new CustomObject
{
Name = user.FullName,
ParticipationStatus = lstStatuses
.Where(m => m.ParticipationStatusID == user.ParticipationStatusID)
.Select(x => x.Label)
.FirstOrDefault() + " Some string here"
} )
.ToList();
Just wanted some confirmation of this possibility.
答案1
得分: 1
假设您已经设置了一个名为ParticipationStatus
的导航属性,您只需要这样做:
var usersWithStatus = await dbContext.Users
.Where(u => u.JoinDate >= someDateTime)
.Select(u => new CustomObject
{
Name = u.FullName,
ParticipationStatus = u.ParticipationStatus.Label + " 这里添加一些字符串"
})
.ToListAsync();
如果您真的想要重复使用您现有的List<ParticipationStatus> lstStatuses = GetStatuses();
(我认为这是一个不好的主意,因为据我们所知,没有保证lstStatuses
实际上包含每个User
引用的每个ParticipationStatus
,而且您的代码似乎没有使用事务来确保隔离或一致的读取),但您可以在加载用户后在内存中进行Join
操作:
List<ParticipationStatus> lstStatuses = GetStatuses();
List<User> users = await dbContext.Users
.Where(u => u.JoinDate >= someDateTime)
.ToListAsync();
List<CustomObject> usersWithStatus = users
.Join(
inner: lstStatuses,
outerKeySelector: u => u.ParticipationStatusID,
innerKeySelector: s => s.ParticipationStatusID,
resultSelector: (u, s) => new CustomObject
{
Name = u.FullName,
ParticipationStatus = s.Label + " 这里添加一些字符串"
}
)
.ToList();
-
Linq的
Join
是一个INNER JOIN
操作(而不是其他类型的连接,比如FULL OUTER JOIN
)。请注意,与SQL的INNER JOIN
一样,inner
和outer
中的多行可能匹配,这可能是不希望的。- 如果任何
User
实体与lstStatuses
中的项目不匹配,那么该User
将被静默排除在结果之外 - 而我认为这是_异常_,如果这是我的程序,我希望它抛出异常而不是静默排除它。
- 如果任何
-
在内部,
.Join
将通过使用临时哈希表高效地将User
和ParticipationStatus
映射到线性时间O(n[u] + n
,而您当前的代码需要二次时间:展开收缩)O(n[u] * n
。展开收缩)
英文:
Assuming you have a ParticipationStatus
navigation-property set-up, all you need is this:
var usersWithStatus = await dbContext.Users
.Where( u => u.JoinDate >= someDateTime )
.Select( u => new CustomObject
{
Name = u.FullName,
ParticipationStatus = u.ParticipationStatus.Label + " Some string here"
} )
.ToListAsync();
If you really want to re-use your existing List<ParticipationStatus> lstStatuses = GetStatuses();
(which I think is a bad idea: because as far as we can see, there is no guarantee that lstStatuses
actually contains every ParticipationStatus
referneced by every User
, and your code dopesn't appear to be using a transaction to ensure isolated or consistent reads), but you can do the Join
in-memory after loading users:
List<ParticipationStatus> lstStatuses = GetStatuses();
List<User> users = await dbContext.Users
.Where( u => u.JoinDate >= someDateTime )
.ToListAsync();
List<CustomObject> usersWithStatus = users
.Join(
inner: lstStatuses,
outerKeySelector: u => u.ParticipationStatusID,
innerKeySelector: s => s.ParticipationStatusID,
resultSelector: ( u, s ) => new CustomObject
{
Name = u.FullName,
ParticipationStatus = s.Label + " Some string here"
}
)
.ToList();
-
Linq's
Join
is anINNER JOIN
operation (and not any other kind of join, likeFULL OUTER JOIN
). Note that, as with SQL'sINNER JOIN
, it is possible for multiple rows ininner
andouter
to match each-other which may be undesirable.- And if any
User
entities aren't matched to alstStatuses
item then thatUser
will be silently excluded from the results - whereas I'd consider that exceptional and if this were my program I'd want it to throw an exception instead of silently excluding it.
- And if any
-
Internally, the
.Join
will efficiently mapUser
andParticipationStatus
in linear-timeO(n[u] + n
by using a temporary hashtable, whereas your current code takes quadratic time:展开收缩)O(n[u] * n
.展开收缩)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论