NullReferenceException让我想要自己开枪

时间:2010-12-29 23:47:32

标签: asp.net asp.net-mvc vb.net nullreferenceexception

好的,曾几何时,我的代码工作了。从那时起我做了一些重构(基本的东西,所以我想),但现在我得到一个空引用异常,我不能很好地弄清楚为什么。

这是它开始的地方。 注意,这是注销方法,但我的所有ActivityLogs部分都抛出了这个错误

Function LogOut(ByVal go As String) As ActionResult
    ActivityLogService.AddActivity(AuthenticationHelper.RetrieveAuthUser.ID, _
                                   IActivityLogService.LogType.UserLogout, _
                                   HttpContext.Request.UserHostAddress)
    ActivityLogService.SubmitChanges()
    'more stuff happens after this'
End Function

该服务非常直接(注意此处的错误

    Public Sub AddActivity(ByVal userid As Integer, ByVal activity As Integer, ByVal ip As String) Implements IActivityLogService.AddActivity
        Dim _activity As ActivityLog = New ActivityLog With {.Activity = activity,
                                                             .UserID = userid,
                                                             .UserIP = ip.IPAddressToNumber,
                                                             .ActivityDate = DateTime.UtcNow}

        ActivityLogRepository.Create(_activity)  ''#ERROR THROWN HERE
    End Sub

服务使用的界面看起来像这样

Public Interface IActivityLogService
    Sub AddActivity(ByVal userid As Integer, ByVal activity As Integer, ByVal ip As String)
    Function GetUsersLastActivity(ByVal UserID As Integer) As ActivityLog
    Sub SubmitChanges()

    ''' <summary> '
    ''' The type of activity done by the user '
    ''' </summary>
    ''' <remarks>Each int refers to an activity. There can be no duplicates or modifications  after this application goes live</remarks> '
    Enum LogType As Integer
        ''' <summary> '
        ''' A new session started '
        ''' </summary> '
        SessionStarted = 1
        ''' <summary> '
        ''' A new user is Added/Created '
        ''' </summary> '
        UserAdded = 2
        ''' <summary> '
        ''' User has updated their profile '
        ''' </summary> '
        UserUpdated = 3
        ''' <summary> '
        ''' User has logged into they system '
        ''' </summary> '
        UserLogin = 4
        ''' <summary> '
        ''' User has logged out of the system '
        ''' </summary> '
        UserLogout = 5
        ''' <summary> '
        ''' A new event has been added '
        ''' </summary> '
        EventAdded = 6
        ''' <summary> '
        ''' An event has been updated '
        ''' </summary> '
        EventUpdated = 7
        ''' <summary> '
        ''' An event has been deleted '
        ''' </summary> '
        EventDeleted = 8
        ''' <summary> '
        ''' An event has received a Up/Down vote '
        ''' </summary> '
        EventVoted = 9
        ''' <summary> '
        ''' An event has been closed '
        ''' </summary> '
        EventCloseVoted = 10
        ''' <summary> '
        ''' A comment has been added to an event '
        ''' </summary> '
        CommentAdded = 11
        ''' <summary> '
        ''' A comment has been updated '
        ''' </summary> '
        CommentUpdated = 12
        ''' <summary> '
        ''' A comment has been deleted '
        ''' </summary> '
        CommentDeleted = 13
        ''' <summary> '
        ''' An event or comment has been reported as spam '
        ''' </summary> '
        SpamReported = 14
    End Enum
End Interface

存储库同样直截了当

Public Class ActivityLogRepository : Implements IActivityLogRepository
    Private dc As MyAppDataContext
    Public Sub New()
        dc = New MyAppDataContext
    End Sub

    ''' <summary> '
    ''' Adds the activity. '
    ''' </summary> '
    ''' <param name="activity">The activity.</param>
    Public Sub Create(ByVal activity As ActivityLog) Implements IActivityLogRepository.Create
        dc.ActivityLogs.InsertOnSubmit(activity)
    End Sub

    ''' <summary> '
    ''' Gets the activities. '
    ''' </summary> '
    ''' <returns>results AsQueryable</returns>
    Public Function Read() As IQueryable(Of ActivityLog) Implements IActivityLogRepository.Read
        Dim activity = (From a In dc.ActivityLogs
                        Order By a.ActivityDate Descending
                        Select a)
        Return activity.AsQueryable
    End Function

    ''' <summary> '
    ''' Submits the changes. '
    ''' </summary> '
    Public Sub SubmitChanges() Implements IActivityLogRepository.SubmitChanges
        dc.SubmitChanges()
    End Sub
End Class

堆栈跟踪如下

  

[NullReferenceException:对象引用未设置为对象的实例。]      E:\ Projects \ MyApp \ MyApp.Core \ Domain \ Services \ ActivityLogService.vb中的MyApp.Core.Domain.ActivityLogService.AddActivity(Int32 userid,Int32 activity,String ip):49      E:\ Projects \ MyApp \ MyApp.Core \ Controllers \ UsersController.vb中的MyApp.Core.Controllers.UsersController.Authenticate(String go):258      lambda_method(Closure,ControllerBase,Object [])+ 163      System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller,Object []参数)+51      System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext,IDictionary 2 parameters) +409 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary 2个参数)+52      System.Web.Mvc。&lt;&gt; c__DisplayClass15.b__12()+127      System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter过滤器,ActionExecutingContext preContext,Func 1 continuation) +436 System.Web.Mvc.<>c__DisplayClass17.<InvokeActionMethodWithFilters>b__14() +61 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList 1个过滤器,ActionDescriptor actionDescriptor,IDictionary 2 parameters) +305 System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +830 System.Web.Mvc.Controller.ExecuteCore() +136 System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +232 System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) +39 System.Web.Mvc.<>c__DisplayClassb.<BeginProcessRequest>b__5() +68 System.Web.Mvc.Async.<>c__DisplayClass1.<MakeVoidDelegate>b__0() +44 System.Web.Mvc.Async.<>c__DisplayClass8 1.b__7(IAsyncResult _)+42      System.Web.Mvc.Async.WrappedAsyncResult`1.End()+ 141      System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult,Object tag)+54      System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult,Object tag)+40      System.Web.Mvc。&lt;&gt; c__DisplayClasse.b__d()+61      System.Web.Mvc.SecurityUtil.b__0(行动f)+31      System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action)+56      System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult)+110      System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result)+38      System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()+ 690      System.Web.HttpApplication.ExecuteStep(IExecutionStep step,Boolean&amp; completedSynchronously)+199

这是连接到调试器时的错误图像。

alt text

这是有问题的数据库架构的图像

alt text

有人能说清楚我在这里可能缺少什么吗?

3 个答案:

答案 0 :(得分:3)

这可能看起来像是我迟钝了,但是你在49号线上为一切添加了空检查吗?

  

MyApp.Core.Domain.ActivityLogService.AddActivity(的Int32   userid,Int32 activity,String ip)in   E:\项目\ MyApp的\ MyApp.Core \域\ SERVICES \   的 ActivityLogService.vb:49

从它的外观来看,这可能是确保ActivityLogRepository不为null。

答案 1 :(得分:1)

以下是调试/避免NullReferenceExceptions的一般概念:

确保所有内容都已初始化。

初始化为null / Nothing不计算。

决定什么可以和什么不能为空

通常,代码库引用的很大一部分在整个或大部分范围内都不应为null。如果是这样,那么你为什么要容忍呢?

积极减少在某些时候允许为null的引用数。目标是使其只能在空状态下找到几个列入白名单的引用。最好在评论中或在ReSharper's annotations之类的内容中明确说明。

注意分白白名单并采取相应行动。

防御性拒绝空参数

方法应该拒绝非白名单的空参数并抛出ArgumentNullException。这样可以立即清除什么引用为null,并且很多时候抛出的引用更接近于空引用的源而不是NullReferenceException,它只在解引用站点抛出。

处理列入白名单的参考文献

如果在列入白名单的引用上引发了异常,请添加适当的代码来处理它。这应该是一个“if”分支;不要捕获NullReferenceException。

所有非列入白名单的空引用都是错误

如果引发异常的引用未列入白名单,则这是一个错误。您必须将空引用追溯到原点。

检查引用的初始化位置。如果它是变量,您只需检查包含方法。

如果是字段,请检查构造函数是否已初始化。然后查找对显式空引用(在Visual Basic中为Nothing)或对白名单引用的赋值。您可能需要跟踪从一个变量/字段到另一个变量/字段的跟踪,直到找到空引用的真实来源。

要修复它,请使用足够的有效引用替换它,或者如果源是列入白名单的引用,则添加“if”子句。

答案 2 :(得分:0)

@gbs指出了我正确的方向。

我的服务中有以下内容

    Private ActivityLogRepository As IActivityLogRepository

    Public Sub New(ByVal ActivityLogRepository As IActivityLogRepository)
        ActivityLogRepository = ActivityLogRepository
    End Sub

不确定我是如何错过它的,改成了它并且它有效

    Private ActivityLogRepository As IActivityLogRepository

    Public Sub New(ByVal _ActivityLogRepository As IActivityLogRepository)
        ActivityLogRepository = _ActivityLogRepository
    End Sub