英文:
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
Joinis anINNER JOINoperation (and not any other kind of join, likeFULL OUTER JOIN). Note that, as with SQL'sINNER JOIN, it is possible for multiple rows ininnerandouterto match each-other which may be undesirable.- And if any
Userentities aren't matched to alstStatusesitem then thatUserwill 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
.Joinwill efficiently mapUserandParticipationStatusin linear-timeO(n[u] + nby using a temporary hashtable, whereas your current code takes quadratic time:展开收缩)O(n[u] * n.展开收缩)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论