我们得到了经典的空引用异常,“对象引用未设置为对象的实例”。那里没什么异常,除了它是直接来自上下文的IdentityUser上发生的。

触发异常的行是:

allUsers.FirstOrDefault(u => u.Id == log.ActionByUserId)


并且在u.Id处触发了异常。在这种情况下,您怎么可能为空?这向我暗示allUsers中的一项为null,但是我不明白当实体框架从数据库中拉出allUsers时将如何发生。这是在只读的Controller Action上发生的,因此我们没有尝试在请求的早期创建用户。

此错误在我们的生产实例上间歇性地发生,但是当我们将同一数据库还原到开发环境中时不会发生。

有关上下文的更多代码(尽管我也将该代码简化为相关部分):

上下文(ApplicationUser类具有自己的上下文,与我们大多数其他实体共享的上下文分开):

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base("DefaultConnection")
    {
    }

    public static ApplicationDbContext Create()
    {
        return new ApplicationDbContext();
    }
}


服务:

public class UserService
{
    private readonly ApplicationDbContext _context;

    public IEnumerable<ApplicationUser> GetUsers()
    {
        var contextUsers = _context.Users;
        return contextUsers;
    }
}


域对象

public class ApplicationUser : IdentityUser
{
    // Id is inherited from IdentityUser
}


控制器动作:

public ActionResult ParticipantLog(int participantId)
{
    var allUsers = UserService.GetUsers();
    var log = LogService.GetParticipantLog(participantId);
    var model = ParticipantLogsModelMapper.Create(log, allUsers);
}


映射器:

public static ParticipantLogsViewModel Create(ParticipantLog log, IEnumerable<ApplicationUser> allUsers)
{
    var actionBy = allUsers.FirstOrDefault(u => u.Id == log.ActionByUserId);
    var model = new ParticipantLogViewModel
    {
        ActionBy = actionBy.DisplayName
    };

    return model;
}

最佳答案

从:

allUsers.FirstOrDefault(u => u.Id == log.ActionByUserId)


如果allUsers不包含任何记录,则返回default(T),在这种情况下为null

我整理了一个最小的控制台应用程序(引入了对Microsoft.AspNet.Identity.EntityFramework的引用:

static void Main(string[] args)
{
    var p = default(ApplicationUser);
}

public class ApplicationUser : IdentityUser
{
    // Id is inherited from IdentityUser
}


p确实为空。从本质上讲,FirstOrDefault扩展方法将返回IEnumerable中的第一个元素,或者如果列表中没有任何内容,则返回<T>的默认元素,这似乎是这种情况。


  此错误在我们的生产实例上间歇性地发生,但是当我们将同一数据库还原到开发环境中时不会发生。


在简化显示的代码的地方,您是否已消除了一些错误检查/处理,从而导致尝试从数据库中检索用户详细信息并返回空集而导致失败?这是您可能会看到此处发生的情况的一种方式。

为了缩小范围,在生产中,您可以在allUsers.FirstOrDefault调用上方放置诊断日志记录行,以检查allUsers.Any()以确认allUsers中是否存在任何项目,然后尝试将其与其他任何诊断相关联你有。开发环境的问题是,尽管它们很少有与生产环境一样大的吸引力,但相比之下,它们通常只有很少的负载。这导致由于仅在没有负载的情况下运行而产生的问题=(

09-05 03:26