有效操作的NullReferenceException

时间:2013-02-19 11:23:46

标签: c# linq entity-framework

我需要从一个查询中获取我的ID(类型Guid):

var firstQuery = 
    from rooms in myEntityContext.Room.Where(t => t.fldClosed == 0)
    join conts in myEntityContext.Cont on rooms.ID equals conts.ItemID
    select new
    {
        ContPrice = conts.Price,
        RoomPrice = rooms.Price
        IDs = rooms.ID
    };

foreach (var t in firstQuery)
{
    t.RoomPrice  = t.ContPrice;
}

然后我对它做了一些操作(更新价格),最后我将ID用于第二个查询。第二个查询不包含这些ID。我用这种方式实现了这个问题:

var myIDs = firstQuery.Select(cr => cr.IDs).ToList();

我的第二个问题是:

var secondQuery = 
    from rooms in myEntityContext.Room.Where(t => t.fldClosed == 0) 
    where !myIDs.Contains(rooms.fldID)                                   
    join conts in myEntityContext.Cont on rooms.ID equals conts.ItemID
    select new
    {
       RoomPrice = conts.fldPrice,
       IDs = rooms.ID
    };

当我在调试器模式下运行此代码并到达此行时:

var myIDs = firstQuery.Select(cr => cr.IDs).ToList();

......提出了一个例外:

  

NullReferenceException
对象引用未设置为对象的实例。

它似乎与第二个查询有关,因为当我将第二个查询转移到一个单独的方法并将ID传递给它时,一切都很完美,但我无法理解为什么它应该考虑一些查询在变量初始化之后。

整个代码是:

var calcDate = DateTime.Now.AddDays(-1);

var firstQuery = 
    from rooms in myEntityContext.Room.Where(t => t.fldClosed == 0)
    join conts in myEntityContext.Cont on rooms.ID equals conts.ItemID
    where conts.date == calcDate
    select new
    {
        ContPrice = conts.Price,
        RoomPrice = rooms.Price
        IDs = rooms.ID
    };

foreach (var t in firstQuery)
{
    t.RoomPrice = t.ContPrice;
}

var myIDs = firstQuery.Select(cr => cr.IDs).ToList();


var secondQuery = 
    from rooms in myEntityContext.Room.Where(t => t.fldClosed == 0) 
    where !myIDs.Contains(rooms.fldID)                                   
    join conts in myEntityContext.Cont on rooms.ID equals conts.ItemID
    where conts.date == calcDate && conts.Code = "01"
    select new
    {
       RoomPrice = conts.fldPrice,
       IDs = rooms.ID
    };

foreach (var t in secondQuery)
{
    ContPrice = Conts.Price,
    RoomPrice = Rooms.Price
}

myEntityContext.SaveChanges();

这是我的堆栈跟踪,如果它有用:

Financial.UI.dll!Financial.UI.Services.Hotels.HotelServiceProxy.CalcProxy.DoCalc(System.DateTime calcDate) Line 5055    C#
Financial.UI.dll!Financial.UI.Pages.Hotel.NightsCalculationPage.CallbackMethod_DoCalc() Line 65 + 0x37 bytes    C#
[Native to Managed Transition]  
Web.UI.dll!Web.UI.SystemCallback.ProcessCallback() Line 228 + 0x3b bytes    C#
Web.UI.dll!Web.UI.SystemCallbackHandler.ProcessRequest(System.Web.HttpContext context) Line 68 + 0x12 bytes C#
System.Web.dll!System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() + 0x156 bytes    
System.Web.dll!System.Web.HttpApplication.ExecuteStep(System.Web.HttpApplication.IExecutionStep step, ref bool completedSynchronously) + 0x46 bytes 
System.Web.dll!System.Web.HttpApplication.PipelineStepManager.ResumeSteps(System.Exception error) + 0x342 bytes 
System.Web.dll!System.Web.HttpApplication.BeginProcessRequestNotification(System.Web.HttpContext context, System.AsyncCallback cb) + 0x60 bytes 
System.Web.dll!System.Web.HttpRuntime.ProcessRequestNotificationPrivate(System.Web.Hosting.IIS7WorkerRequest wr, System.Web.HttpContext context) + 0xbb bytes   
System.Web.dll!System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(System.IntPtr rootedObjectsPointer, System.IntPtr nativeRequestContext, System.IntPtr moduleData, int flags) + 0x1f3 bytes   
System.Web.dll!System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(System.IntPtr rootedObjectsPointer, System.IntPtr nativeRequestContext, System.IntPtr moduleData, int flags) + 0x1f bytes  
[Native to Managed Transition]  
[Managed to Native Transition]  
System.Web.dll!System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(System.IntPtr rootedObjectsPointer, System.IntPtr nativeRequestContext, System.IntPtr moduleData, int flags) + 0x350 bytes   
System.Web.dll!System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(System.IntPtr rootedObjectsPointer, System.IntPtr nativeRequestContext, System.IntPtr moduleData, int flags) + 0x1f bytes  
[Appdomain Transition]  

5 个答案:

答案 0 :(得分:5)

好吧,堆栈跟踪 非常有用:我假设你发布的代码是DoCalc()方法。但是,您发布的行不一定是代码中的第5055行:

var myIDs = firstQuery.Select(cr => cr.IDs).ToList();

要在此行上发生NullReferenceExceptionfirstQuery必须为null,否则firstQuery.Select(cr => cr.IDs)必须返回null ...

但是,如果这两种情况下你都会获得ArgumentNullException a NullReferenceException。所以这不是错误的界限。


另外,你的代码甚至都没有运行!

例如,在下面的部分中,您应该得到编译时错误:

foreach (var t in firstQuery)
{
    t.RoomPrice = t.ContPrice;
}
  

无法将属性或索引器'AnonymousType#1.RoomPrice'分配给 - 它是只读的

你在这里想做什么......我不知道:

foreach (var t in secondQuery)
{
    ContPrice = Conts.Price,
    RoomPrice = Rooms.Price
}

最有可能发生的事情

nullmyEntityContext.Room中有myEntityContext.Cont。查看他们的内容并验证这一点。如果您仍然不确定,当您收到异常时,请在Visual Studio中单击“将异常详细信息复制到剪贴板”(在异常窗口中)并将其粘贴到您的问题中。

答案 1 :(得分:3)

此代码无法编译。因此假设它在某一点上进行了编译,并且所有的Rooms和Cont都是实际的实例,其中没有空对象,它可能是使用匿名返回;

试试这个

public class QueryResult
{
    public decimal ContPrice; //whatever your types are

    public decimal RoomPrice;

    public int IDs;
}

然后像这样使用它:

var firstQuery =
    from rooms in myEntityContext.Room.Where(t => t.fldClosed == 0)
    join conts in myEntityContext.Cont on rooms.ID equals conts.ItemID
    where conts.date == calcDate
    select new QueryResult
                {
                    ContPrice = conts.Price,
                    RoomPrice = rooms.Price,
                    IDs = rooms.ID
                };

var firstQueryResult = firstQuery.ToList();

foreach (var t in firstQueryResult)
{
    t.RoomPrice = t.ContPrice;
}

正如其他人所说,避免不止一次列举。

同时删除第二个查询并初步完成第一个工作......第二个问题就出现了一些问题。首先,您再次拥有匿名类型。这是一种滥用,因为它们应该用于linq之间;你应该解决一个强大的类型。其次,

...&& conts.Code =“01”

不编译,应该是:

conts.Code.Equals("01")

我还建议将您的查询分成更小的部分;也许是这样的

var roomsOpenQuery = myEntityContext.Room.Where(t => t.fldClosed == 0);
var roomsOpenQueryResolved = roomsOpenQuery.ToList();
var contQuery = myEntityContext.Cont
    .Where(t => roomsOpenQueryResolved.Any(r => r.ID == t.ItemID))
    .Where(x => x.date == calcDate);


var availableRooms =
    contQuery
        .Join(roomsOpenQueryResolved,
                c => c.ItemID,
                r => r.ID,
                (c, r) => new AvailableRoom()
                            {
                                ContPrice = c.Price,
                                RoomPrice = r.Price,
                                IDs = c.ItemID
                            })
        .ToList();


//Price Adjustment etc...

答案 2 :(得分:2)

我假设var FirstQuery解析为IEnumerable<出T>。

您无法多次访问Enumerable的内容。

尝试在第一个查询中创建一个List:

var FirstQuery = (from rooms in myEntityContext.Room.Where(t => t.fldClosed == 0)                                    
    join Conts in myEntityContextt.Cont on rooms.ID equals Conts.ItemID
    select new
    {
        RoomPrice = Conts.fldPrice,
        IDs = rooms.ID
    }).ToList();

如果此行失败,那么myEntityContext.Mark或myEntityContext.Cont可能是空对象

答案 3 :(得分:1)

ID ID = rooms.ID可能会为空。

尝试添加此内容: var myIDs = FirstQuery.ToList()。选择(Cr => Cr.IDs).ToList();

答案 4 :(得分:1)

var myIDs = new List<int>();
if( firstQuery.Count() > 0)
myIds =  firstQuery.Select(cr => cr.IDs).ToList();