9

I need to get my IDs (type Guid) from one query:

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;
}

Then I do some operation on it (updating the price), and finally I use the IDs for a second query. That second query doesn't contain these IDs. I implemented this problem in this way:

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

And my second query is:

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
    };

When I run this code in debugger mode and reach this line:

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

...an exception is raised:

NullReferenceException
Object reference not set to an instance of an object.

It seems that it has something to do with the second query because when I transfer the second query to a separate method and pass IDs to it everything works perfectly, but I can't understand why it should consider some query which is written after the variable initializing.

The whole code is:

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();

Here is my stack trace, if it is useful:

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]  
18
  • why the down vote without any comment? Commented Feb 19, 2013 at 11:38
  • 3
    Maybe a full stack frame would help Commented Feb 25, 2013 at 13:12
  • 1
    @MaryamArshi You really need to provide us with the stack trace at the point of the exception. Otherwise we cannot help you. I doubt that the exception occurred in the line you specified. There is also a stack trace string you can get from the thrown Exception in Visual Studio. Just copy it and add it to your post. Commented Feb 27, 2013 at 12:21
  • 1
    @MaryamArshi You should still post the stack trace here. It is the most important piece of information for solving such exceptions. Since you can't find out why you get this exception, let others have a look. Commented Feb 27, 2013 at 13:04
  • 1
    @Maryam Run the code as the release build and you probably won't encounter any errors. Commented Feb 27, 2013 at 17:21

5 Answers 5

5
+25

Well, the stack trace is useful: I assume the code you posted is in the DoCalc() method. However, the line you posted cannot possibly be line 5055 in your code:

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

For a NullReferenceException to occur on this line, either firstQuery would have to be null or firstQuery.Select(cr => cr.IDs) would have to return null...

However, if this were the case you'd be getting an ArgumentNullException in both cases, not a NullReferenceException. So that's not the line with the error.


Also, your code shoudn't even run!

For example, on the following piece you should get a compile-time error:

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

Property or indexer 'AnonymousType#1.RoomPrice' cannot be assigned to -- it is read only

And what you are trying to do here... I don't know:

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

What most likely happens

You have a null in myEntityContext.Room or in myEntityContext.Cont. Look at their content and verify this. If you are still not sure, when you get the exception, click "Copy exception detail to the clipboard" in Visual Studio (on the exception window) and paste it into your question.

Sign up to request clarification or add additional context in comments.

1 Comment

It's just a simple query to update prices, I didn't do that in the main query because later I would like to add some more calculations to it.but I really don't have any compile error on my previous lines, but I will check them again.Thanks
3

This code doesn't compile. So assuming at one point it did compile, and that all your Rooms and Cont are actual instances with no null objects within them, it could be the use of the anonymous return;

try this

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

    public decimal RoomPrice;

    public int IDs;
}

then use it like this:

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;
}

And as others have said, avoid enumerating more than once.

Also remove the second query and get the first work initially... you have a few problems with the second. firstly, you have anonymous types again as a result. This is an abuse as they are supposed to be used inter-linq; you should resolve to a strong type. Secondly,

... && conts.Code = "01"

doesn't compile and should be:

conts.Code.Equals("01")

I'd also recommend breaking up your Query into smaller parts; perhaps something like this

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...

Comments

2

I assume that var FirstQuery resolves to IEnumerable< out T >.

You cannot access the contents of an Enumerable more than once.

try creating a List in the first query:

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();

If this line fails then myEntityContext.Mark or myEntityContext.Cont are probably the null objects

2 Comments

I tried this solution too but it didn't work either.and there is no null in my query, it returns about 826 rows and I checked that they are not null, Thanks anyway
@qujck In general you can access the contents of an enumerable more than once. Only some very specific enumerables might not yield the same results when re-enumerated.
1

IDs IDs = rooms.ID can possibly get a null.

Try adding this: var myIDs = FirstQuery.ToList().Select(Cr => Cr.IDs).ToList();

Comments

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.