C#Complex Linq - 在子查询中加入两个表

时间:2015-10-30 19:41:50

标签: c# sql-server entity-framework linq exception

我目前正在使用一个使用非常复杂的数据库的系统。

我需要从多个表和关联中编译信息以显示这样的列表(我有很多):

[List] (Class `List`)
     [Id]
     [EntityId]
     [Name]
     [Description]
     [Users] (From `List<User> List.AssignedUsers` joined to `List<ListMember> List.Members`)
         [Id]
         [EntityId]
         [Username]
         [FullName]
         [Email]
         [ListId]
         [Order] (From `ListOrder` property in `ListMember` object)
         [Status] (From `Status` property in `ListMember` object)
             [Id]
             [NameEn]
             [NameFr]
             [Color]
             [Type]
             [Tag]
             [Options]

在此,List.AssignedUsers是可以访问列表的用户列表。 List.Members是列表中当前活动用户的列表,包含其状态。如果AssignedUser不在Members中,则StatusOrder属性必须为空。

以下是设计数据库的方式:

DB Diagram

这是我尝试使用的代码:

var lists =
    await (from l in db.Lists.Include("Members").Include("AssignedUsers")
           where l.DateDeleted == null
           select new ListModel
           {
               Id = l.Id,
               EntityId = l.EntityId,
               Name = l.Name,
               Description = l.Description,
               Users = (
                   from u in l.AssignedUsers
                   join lms in l.Members on u.Id equals lms.UserId into members
                   from lm in members.DefaultIfEmpty()
                   select new UserModel
                   {
                       Id = u.Id,
                       EntityId = u.EntityId,
                       Username = u.Username,
                       FullName = u.FullName,
                       Email = u.Email,
                       ListId = l.Id,
                       Order = (lm == null ? lm.ListOrder : -1),
                       Status = (lm != null ? new StatusModel
                       {
                           Id = lm.Status.Id,
                           Type = lm.Status.Type,
                           Color = lm.Status.Color,
                           Tag = lm.Status.Tag,
                           NameEn = lm.Status.NameEn,
                           NameFr = lm.Status.NameFr,
                           Options = lm.Status.AvailableOptions
                       } : null)
                   }
               ).ToList()
           }).ToListAsync();

return lists;

问题是这个查询非常慢,而不是返回结果,我的w3wp.exe进程崩溃,有一个很好的窗口告诉我.NET崩溃了。除了以下内容之外,错误日志没有说明:

Faulting application name: w3wp.exe, version: 10.0.10240.16384, time stamp: 0x559f3dad
Faulting module name: ntdll.dll, version: 10.0.10240.16430, time stamp: 0x55c599e1
Exception code: 0xc00000fd
Fault offset: 0x0003dcb9
Faulting process id: 0x4998
Faulting application start time: 0x01d1134884f4b8dd
Faulting application path: C:\Windows\SysWOW64\inetsrv\w3wp.exe
Faulting module path: C:\Windows\SYSTEM32\ntdll.dll
Report Id: 52069c20-912c-428a-b4fc-271851dbaba0
Faulting package full name: 
Faulting package-relative application ID: 

现在,我尝试了其他一些方法,但我正在寻找性能最好的方法,如果LINQ不能这样做,我会直接在SQL中做到这一点!

1 个答案:

答案 0 :(得分:1)

这很慢,因为您阻止了库使用单个查询,因为您嵌套了ToList次调用。

如果你只是建立一个很好的对象,连接和所有的描述,并在最后调用ToArray(为什么列表?),它会很好,但你的方式调用的第一部分在开头的查询,然后返回的每个项目调用子查询来填充结果。

至于为什么它会崩溃,这是同样写得很好的条件:lm == null ? lm.ListOrder : -1 - 你可以通过简单的调试过程轻松地看到它。