object reference not set error in mvc5 - linq

i am using viewmodel to display data from two tables (Eta and Voyage) and i have used viewmodel name as 'EtaVoyage'.The problem is when i use this query, it gives me this error
Additional information: Object reference not set to an instance of an object.
var Test = db.Etas.AsEnumerable().Select(v => new EtaVoyage()
{
ShippingAgent = v.ShippingAgent,
VesselInformation = v.VesselInformation,
Port = v.Port,
CPort = v.CPort,
EtaDate = v.EtaDate,
GoodsCarried = v.VoyageDetails.FirstOrDefault().GoodsCarried,
VoyagePurpose = v.VoyageDetails.FirstOrDefault().VoyagePurpose
}).ToList();
return View(Test);
But when i comment the last two fields related to voyagedetails, it is working fine.
var Test = db.Etas.AsEnumerable().Select(v => new EtaVoyage()
{
ShippingAgent = v.ShippingAgent,
VesselInformation = v.VesselInformation,
Port = v.Port,
CustomPort = v.CustomPort,
EtaDate = v.EtaDate,
// GoodsCarried = v.VoyageDetails.FirstOrDefault().GoodsCarried,
// VoyagePurpose = v.VoyageDetails.FirstOrDefault().VoyagePurpose
}).ToList();
return View(Test);
i need to display these two columns too in the index page.

FirstOrDefault() might return null,
Enumerable.FirstOrDefault : Return Value
Type: TSource
default(TSource) if source is empty; otherwise, the first element in source.
Use
.Select(i=>i.GoodsCarried).FirstOrDefault()
....
GoodsCarried = v.VoyageDetails.Select(i=>i.GoodsCarried).FirstOrDefault(),
VoyagePurpose = v.VoyageDetails.Select(i=>i.VoyagePurpose).FirstOrDefault()
}).ToList();

The collection v.VoyageDetails must not contain any items, and therefore FirstOrDefault is returning the default (null for reference types). You can handle this special case separately, or, since you seem to just be flattening a collection, you can use a null-conditional operator to set GoodsCarried and VoyagePurpose to null when FirstOrDefault returns null.
GoodsCarried = v.VoyageDetails.FirstOrDefault()?.GoodsCarried,
VoyagePurpose = v.VoyageDetails.FirstOrDefault()?.VoyagePurpose
Note it is also possible that:
v.VoyageDetails itself is null, depending on how your class is initialized and data is loaded. If this is expected, you may need to handle this case as well. Again with the null-conditional operator:
GoodsCarried = v.VoyageDetails?.FirstOrDefault()?.GoodsCarried,
VoyagePurpose = v.VoyageDetails?.FirstOrDefault()?.VoyagePurpose
If you are using an ORM such as Entity Framework, the VoyageDetails collection is not eagerly loaded, it may simply not be retrieving the data for you. If this applies, you need to explicitly load the data in the collection. In Entity Framework this is done with an Include call. Note your AsEnumerable() call will stop Linq-To-Sql from optimizing this into a single query, but I assume this is intentional:
db.Etas.Include(x => x.VoyageDetails).AsEnumerable().Select(...)

Related

No result in my result view of Quick watch but the result is under non-public members

in my query when i see quick watch, under the result it returns no result but when go through Non-Public members under source and result in view I see all my results,how can i access to them? and why its like this?im using PostgreSQL for my database
var test = (from t in db.v_vpn_gateway.AsEnumerable()
where t.turbine_id.ToString() == id
select new TurbineDvce
{
Comments = "VPN Gateway",
Description = string.Empty,
DeviceIP = t.vpn_gateway.ToString(),
DeviceType = t.device_type,
FirmwareVersion = string.Empty,
Model = t.model,
Password = string.Empty,
Phone = string.Empty,
Producer = t.producer,
PublicIP = t.vpn_public_ip.ToString(),
TurbineId = t.turbine_id.ToString(),
Username = string.Empty
});
Looks like you need to "Hydrate" the result. The way Linq works with Lazy Evaluation, really you are just getting a place holder back for the test variable, and the actual query will run when the test variable is used by other code. Since you have a "where" clause, you should be expecting back an IEnumerable, so you can add ToList() or ToArray() to the end of your query, which will force the query to run and store the list or array in your test variable. That should give you access to that data right after the query runs.

Unable to create a constant value - only primitive types or Enumeration types allowed

I have seen some questions related to this Exception here but none made me understand the root cause of the problem. So here we have one more...
var testquery =
((from le in context.LoanEMIs.Include("LoanPmnt")
join lp in context.LoanPmnts on le.Id equals lp.LoanEMIId
where lp.PmntDtTm < date && lp.IsPaid == false
&& le.IsActive == true && lp.Amount > 0
select new ObjGetAllPendingPmntDetails
{
Id = lp.Id,
Table = "LoanEMI",
loanEMIId = lp.LoanEMIId,
Name = le.AcHead,
Ref = SqlFunctions.StringConvert((double)le.FreqId),
PmntDtTm = lp.PmntDtTm,
Amount = lp.Amount,
IsDiscard = lp.IsDiscarded,
DiscardRemarks = lp.DiscardRemarks
}).DefaultIfEmpty(ObjNull));
List<ObjGetAllPendingPmntDetails> test = testquery.ToList();
This query gives the following Exception Message -
Unable to create a constant value of type CashVitae.ObjGetAllPendingPmntDetails. Only primitive types or enumeration types are supported in this context.
I got this Exception after I added the SQL function statement to convert le.FreqId which is a byte to a string as ToString() is not recognized in the LINQ Expression Store.
ObjGetAllPendingPmntDetails is a partial class in my model which is added as it is used too many times in the code to bind data to tables.
It has both IDs as long, 'Amount' as decimal, PmntDtTm as Datetime,IsDiscard as bool and remaining all are string including 'Ref'.
I get no results as currently no data satisfies the condition. While trying to handle null, I added DefaultIfEmpty(ObjNull) and ObjNull has all properties initialized as follows.
ObjGetAllPendingPmntDetails ObjNull = new ObjGetAllPendingPmntDetails()
{ Id = 0, Table = "-", loanEMIId = 0, Name = "-", Ref = "-",
PmntDtTm = Convert.ToDateTime("01-01-1900"),
Amount = 0, IsDiscard = false, DiscardRemarks = "" };
I need this query to work fine as it has Union() called on it with 5 other queries. All returning the same ObjGetAllPendingPmntDetails columns. But there is some problem as this query has no data satisfying the conditions and the Exception Shared Above.
Any suggestions are appreciated as I am unable to understand the root cause of the problem.
#AndrewCoonce is right, the .DefaultIfEmpty(ObjNull) is the culprit here. Entity Framework turns DefaultIfEmpty into something like...
CASE WHEN ([Project1].[C1] IS NULL) THEN #param ELSE [Project1].[Value] END AS [C1]
...but there's no way to coerce an instance of ObjGetAllPendingPmntDetails into something that can take the place of #param, so you get an exception.
If you move the DefaultIfEmpty call to after the ToList it should work correctly (although you'll need to call ToList again after that if you really want a concrete list instance).

Linq with DynamicObject

I have List where MyType : DynamicObject. The reason for MyType inheriting from DynamicObject, is that I need a type that can contain unknown number of properties.
It all works fine until I need to filter List. Is there a way I can do a linq that will do something like this:
return all items where any of the properties is empty string or white space?
(from the comment) can I do above linq query with List?
Yes, here is how you can do it with ExpandoObject:
var list = new List<ExpandoObject>();
dynamic e1 = new ExpandoObject();
e1.a = null;
e1.b = "";
dynamic e2 = new ExpandoObject();
e2.x = "xxx";
e2.y = 123;
list.Add(e1);
list.Add(e2);
var res = list.Where(
item => item.Any(p => p.Value == null || (p.Value is string && string.IsNullOrEmpty((string)p.Value)))
);
The ExpandoObject presents an interface that lets you enumerate its property-value pairs as if they were in a dictionary, making the process of checking them a lot simpler.
Well as long as each object's properties are not unknown internally to themselves you could do it.
There isn't a great generic way to test all the properties of a dynamic object, if you don't have control over the DynamicObject you hope the implementer implemented GetDynamicMemberNames() and you can use the nuget package ImpromptuInterface's methods for getting the property names and dynamically invoking those names.
return allItems.Where(x=> Impromptu.GetMemberNames(x, dynamicOnly:true)
.Any(y=>String.IsNullOrWhiteSpace(Impromptu.InvokeGet(x,y));
Otherwise, since it's your own type MyType you can add your own method that can see internal accounting for those member values.
return allItems.Where(x => x.MyValues.Any(y=>String.IsNullOrWhitespace(x));

Selecting an Entity into a property of an object won't populate its related entities despite .Include() being used. Why is this?

I'm using Entity Framework 4.1, and I'm trying to select an entity while also including one of its related collections of entities. This is the standard way of doing this with LINQ. (MacAddressPool is one-to-many with AllowedPartNumbers.)
var query =
from p in MacAddressPools.Include( "AllowedPartNumbers" )
where p.MacAddressPoolID == 2
select p;
var pool = query.FirstOrDefault();
Console.WriteLine( pool.AllowedPartNumbers.IsLoaded );
"True"
Instead, I might want to do this to get other data at the same time:
var query =
from p in MacAddressPools.Include( "AllowedPartNumbers" )
where p.MacAddressPoolID == 2
select new
{
Pool = p,
AssignedMacAddressCount = pool.MacAddressAssignments.Count( a => a.AssignedDate != null )
};
var pool = query.FirstOrDefault().Pool;
Console.WriteLine( pool.AllowedPartNumbers.IsLoaded );
"False"
Why is the related entity collection not loaded this time? It doesn't matter if I use an anonymous type or some class. It won't load the AllowedPartNumbers. The SQL command that is used doesn't even join the AllowedPartNumbers table.
I discovered that I can do this:
var query =
from p in MacAddressPools
where p.MacAddressPoolID == 2
select new
{
Pool = p,
AllowedPartNumbers = p.AllowedPartNumbers,
AssignedMacAddressCount = pool.MacAddressAssignments.Count( a => a.AssignedDate != null )
};
var pool = query.FirstOrDefault().Pool;
Console.WriteLine( pool.AllowedPartNumbers.IsLoaded );
"True"
Even though I'm just going to ignore that AllowedPartNumbers property on my anonymous type, having it there makes LINQ to Entities populate the AllowedPartNumbers property on the pool itself. I don't even need the .Include().
Is there any reason for this strange behavior?
Include() is not guaranteed to work in subqueries and projections. You can find a detailed description of this issue at the MSDN forum and a related post by Shawn Wildermuth: Caution when Eager Loading in the Entity Framework.
Loading related objects is by default set to false, because it may cause a very great performance degradation, think of an object with a collection containing hundreds or thousands of item, what will be happened when you load that object!
Make the lazy loading of entity framework enabled and it will load the related properties upon access(calling the get of property)
context.ContextOptions.LazyLoadingEnabled = true;

LINQ to SQL bug (or very strange feature) when using IQueryable, foreach, and multiple Where

I ran into a scenario where LINQ to SQL acts very strangely. I would like to know if I'm doing something wrong. But I think there is a real possibility that it's a bug.
The code pasted below isn't my real code. It is a simplified version I created for this post, using the Northwind database.
A little background: I have a method that takes an IQueryable of Product and a "filter object" (which I will describe in a minute). It should run some "Where" extension methods on the IQueryable, based on the "filter object", and then return the IQueryable.
The so-called "filter object" is a System.Collections.Generic.List of an anonymous type of this structure: { column = fieldEnum, id = int }
The fieldEnum is an enum of the different columns of the Products table that I would possibly like to use for the filtering.
Instead of explaining further how my code works, it's easier if you just take a look at it. It's simple to follow.
enum filterType { supplier = 1, category }
public IQueryable<Product> getIQueryableProducts()
{
NorthwindDataClassesDataContext db = new NorthwindDataClassesDataContext();
IQueryable<Product> query = db.Products.AsQueryable();
//this section is just for the example. It creates a Generic List of an Anonymous Type
//with two objects. In real life I get the same kind of collection, but it isn't hard coded like here
var filter1 = new { column = filterType.supplier, id = 7 };
var filter2 = new { column = filterType.category, id = 3 };
var filterList = (new[] { filter1 }).ToList();
filterList.Add(filter2);
foreach(var oFilter in filterList)
{
switch (oFilter.column)
{
case filterType.supplier:
query = query.Where(p => p.SupplierID == oFilter.id);
break;
case filterType.category:
query = query.Where(p => p.CategoryID == oFilter.id);
break;
default:
break;
}
}
return query;
}
So here is an example. Let's say the List contains two items of this anonymous type, { column = fieldEnum.Supplier, id = 7 } and { column = fieldEnum.Category, id = 3}.
After running the code above, the underlying SQL query of the IQueryable object should contain:
WHERE SupplierID = 7 AND CategoryID = 3
But in reality, after the code runs the SQL that gets executed is
WHERE SupplierID = 3 AND CategoryID = 3
I tried defining query as a property and setting a breakpoint on the setter, thinking I could catch what's changing it when it shouldn't be. But everything was supposedly fine. So instead I just checked the underlying SQL after every command. I realized that the first Where runs fine, and query stays fine (meaning SupplierID = 7) until right after the foreach loop runs the second time. Right after oFilter becomes the second anonymous type item, and not the first, the 'query' SQL changes to Supplier = 3. So what must be happening here under-the-hood is that instead of just remembering that Supplier should equal 7, LINQ to SQL remembers that Supplier should equal oFilter.id. But oFilter is a name of a single item of a foreach loop, and it means something different after it iterates.
I have only glanced at your question, but I am 90% sure that you should read the first section of On lambdas, capture, and mutability (which includes links to 5 similar SO questions) and all will become clear.
The basic gist of it is that the variable oFilter in your example has been captured in the closure by reference and not by value. That means that once the loop finishes iterating, the variable's reference is to the last one, so the value as evaluated at lambda execution time is the final one as well.
The cure is to insert a new variable inside the foreach loop whose scope is only that iteration rather than the whole loop:
foreach(var oFilter in filterList)
{
var filter = oFilter; // add this
switch (oFilter.column) // this doesn't have to change, but can for consistency
{
case filterType.supplier:
query = query.Where(p => p.SupplierID == filter.id); // use `filter` here
break;
Now each closure is over a different filter variable that is declared anew inside of each loop, and your code will run as expected.
Working as designed. The issue you are confronting is the clash between lexical closure and mutable variables.
What you probably want to do is
foreach(var oFilter in filterList)
{
var o = oFilter;
switch (o.column)
{
case filterType.supplier:
query = query.Where(p => p.SupplierID == o.id);
break;
case filterType.category:
query = query.Where(p => p.CategoryID == o.id);
break;
default:
break;
}
}
When compiled to IL, the variable oFilter is declared once and used multiply. What you need is a variable declared separately for each use of that variable within a closure, which is what o is now there for.
While you're at it, get rid of that bastardized Hungarian notation :P.
I think this is the clearest explanation I've ever seen: http://blogs.msdn.com/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx:
Basically, the problem arises because we specify that the foreach loop is a syntactic sugar for
{
IEnumerator<int> e = ((IEnumerable<int>)values).GetEnumerator();
try
{
int m; // OUTSIDE THE ACTUAL LOOP
while(e.MoveNext())
{
m = (int)(int)e.Current;
funcs.Add(()=>m);
}
}
finally
{
if (e != null) ((IDisposable)e).Dispose();
}
}
If we specified that the expansion was
try
{
while(e.MoveNext())
{
int m; // INSIDE
m = (int)(int)e.Current;
funcs.Add(()=>m);
}
then the code would behave as expected.
The problem is that you're not appending to the query, you're replacing it each time through the foreach statement.
You want something like the PredicateBuilder - http://www.albahari.com/nutshell/predicatebuilder.aspx

Resources