IQueryable throws null ref Exception while using FirstOrDefault(where) [duplicate] - entity-framework

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 4 years ago.
I am doing a repository call in EF, as soon as i access First or default i am getting null reference exception, could any body help with inputs?
is there any way to check if the Entity values are null? so that i can avoid Exception.
public TEntity GetSingle(Func<TEntity, bool> where, params Expression<Func<TEntity, object>>[] navigationProperties)
{
TEntity item = null;
using (var context = new CDREntities())
{
IQueryable<TEntity> dbQuery = context.Set<TEntity>();
below line returns 56 entities with null values, because i dont have any entities in the table
//Apply eager loading
dbQuery = navigationProperties.Aggregate(dbQuery, (current, navigationProperty) => current.Include(navigationProperty));
below is the place where i get null reference exception when i access above null entities, is there any thing wrong with the below statement?
item = dbQuery
.AsNoTracking() //Don't track any changes for the selected item
.FirstOrDefault(where); //Apply where clause
}
return item;
}

Have you tried checking whether it is null or not
if(item == null)
{
// Handle null case
}
The query is simple, FirstOrDefault will return the first item in a db, or the first item in a collection of results, if there are no items in the table being queried, naturally there's nothing for EF to return.
EF handles such cases by returning null as it's appropriate. Simply check if the response is null, the only other way to avoid it is to have something in the database for it to return or performing a count operation against the table its self which is pointless if you are then going to have to query the table again for the data you just checked for it existing or not.
Also why are you creating a method called Single? The implementation of it is wrong for one, secondly the Single method exposed in Entity Framework behaves differently, it will throw an exception if more than 1 item matches the query.
Another point I'm wondering is why you're receiving 56 null items if your table is empty???

Related

How to retrieve generated fields such as generated id or updated_at field by a trigger during insert/update in springboot

In postgres it's possible to retrieve computed values using returning. I have a generated id field and a field called updated_at that is updated by a trigger whenever a row is modified.
I'd like to achieve something like this but looks like it's not working. Not sure it's the right syntax for bulk insert.
#Query(value = "INSERT INTO entities VALUES :values RETURNING *",nativeQuery = true)
List<Entity> insertAndReturn(#Param("values") List<Entity> entities);
The error is:
java.lang.IllegalStateException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing
I have also looked into jdbctemplate but it seems we are losing the benefit of entity mapping and we need to write own customized mapper.
That's not going to work. Native SQL doesn't support multi-valued parameters. You have to list all parameters individually. You can try something like this
default List<Entity> insertAndReturn(#Param("values") List<Entity> entities) {
for (int i = 0; i < entities.size(); i++ ) {
entities.set(i, insertAndReturn(entities.get(i)));
}
return entities;
}
default Entity insertAndReturn(Entity entity) {
return insertAndReturn(entity.getColumn1(), entity.getColumn2());
}
#Query(value = "INSERT INTO entities_table(column1, column2) VALUES (:column1, :column2) RETURNING *",nativeQuery = true)
Entity insertAndReturn(#Param("column1") String column1, #Param("column2") String column2);

Filtering related entities in entity framework 6

I want to fetch the candidate and the work exp where it is not deleted. I am using repository pattern in my c# app mvc.
Kind of having trouble filtering the record and its related child entities
I have list of candidates which have collection of workexp kind of throws error saying cannot build expression from the body.
I tried putting out anonymous object but error still persist, but if I use a VM or DTO for returning the data the query works.
It's like EF doesn't like newing up of the existing entity within its current context.
var candidate = dbcontext.candidate
.where(c=>c.candiate.ID == id).include(c=>c.WorkExperience)
.select(e=>new candidate
{
WorkExperience = e.WorkExperience.where(k=>k.isdeleted==false).tolist()
});
Is there any workaround for this?
You cannot call ToList in the expression that is traslated to SQL. Alternatively, you can start you query from selecting from WorkExperience table. I'm not aware of the structure of your database, but something like this might work:
var candidate = dbcontext.WorkExperience
.Include(exp => exp.Candidate)
.Where(exp => exp.isdeleted == false && exp.Candidate.ID == id)
.GroupBy(exp => exp.Candidate)
.ToArray() //query actually gets executed and return grouped data from the DB
.Select(groped => new {
Candidate = grouped.Key,
Experience = grouped.ToArray()
});
var candidate =
from(dbcontext.candidate.Include(c=>c.WorkExperience)
where(c=>c.candiate.ID == id)
select c).ToList().Select(cand => new candidate{WorkExperience = cand.WorkExperience.where(k=>k.isdeleted==false).tolist()});

EF 4.1 : Bad reading (query result mixed/merged from database and in memory values)

I have an entity for example which has a foreign key to another entity:
public entityA
{
....
[ForeignKey("State")]
public virtual int StateId { get; set; }
public virtual States State { get; set; }
....
}
IDbSet<entityA> EntitiesA;
StateId is initially initialized to 10 by default.
I initialize my context to database and I use always the same. Once initialized with using clause I do some changes on some entities in EntitiesA collection (that is setting StateId to 20) but I do not commit changes to database using context.SaveChanges() because I do not want at this point.
After modifying some entities I reach to a point in my app that I do the following:
IQueryable<EntityA> entities =
context.EntitiesA.Where(e => e.StateId == 10);
foreach (EntityA _currentEntity in entities)
{
....
}
At this point, as I have not perfomed savechanges to database, entities in database continues having its state to 10 (not to the modified 20) so condition e.StateId == 10 is satisfied but entities is containing items whose StateId is 20 so I do not understand this....
The desired behaviour would be that condition e.StateId not being satisfied for those that has been modified previously to 20 and entities only containing those items whose stateid is still 10 (not modified).
Any ideas? It seems like query is launched against database and the results in fact are taken from in memory...
The behaviour is expected but yes, it is confusing. In order to fix the problem you have to run a weird looking query like this for example:
IEnumerable<EntityA> entities = context.EntitiesA
.Where(e => e.StateId == 10) // LINQ-to-Entities = filter in database
.AsEnumerable()
.Where(e => e.StateId == 10); // LINQ-to-Objects = filter in memory
foreach (EntityA _currentEntity in entities)
{
....
}
What happens is that your query retrieves entities with StateId = 10 in the database. When the result is returned EF runs through all loaded rows and checks if an entity that has the same key is already attached to the context.
If yes, it returns this attached entity in the enumeration with all the values that it currently has in memory. EF does not update the values from the loaded row by default, so that the StateId of your modified entities is still 20.
If no, it attaches the new entity (that has StateId 10) to the context and returns it as part of the enumeration.
As a result you get this mix of entities that have StateId 10 or 20. Basically your query means: "Give me all entities that have a StateId of 10 in the database."
By appending .AsEnumerable().Where(e => e.StateId == 10) to the query you filter out the entities that have a StateId of 10 in memory.

DbSet.Local is empty aftering adding to it

I'm new to Entity Framework. I wanted to query objects before calling SaveChanges(). I searched a bit and found that I should use Dbset.Local. But my query returns always null. Here is my code.
I add to context here:
DB.RFH_ComplexRequestPersons.Add(person);
And query it here:
var model = DB.RFH_ComplexRequestPersons.Local.Where(d => d.FKComplexRequestID == requestID);
By the way DB is my context.

Using FirstOrDefault() in query

Is there a way to use FirstOrDefault() inside a complex query but not throw an exception if it returns null value?
My query:
contex.Table1.Where(t => t.Property == "Value").FirstOrDefault()
.Object.Table2.Where(t => t.Property2 == "Value2").FirstOrDefault();
If the query on the first table (Table1) doesn't return an object the code throws an exception. Is there a way to make it return just null?
Try a SelectMany on Table2, without the intermediate FirstOrDefault():
context.Table1.Where(t1 => t1.Property1 == "Value1")
.SelectMany(t1 => t1.Table2.Where(t2 => t2.Property2 == "Value2"))
.FirstOrDefault();
Also, you might want to use SQL Profiler to check the SQL that is being sent by EF. I believe the query as constructed in your question will result in two queries being sent to the database; one for each FirstOrDefault().
You could build your own helper function, that takes IEnumerable
public static TSource CustomFirstOrDefault<TSource>(this IEnumerable<TSource> source)
{
return source.FirstOrDefault() ?? new List<TSource>();
}
This would effectively return an empty list, which, when called upon, providing your code in your Object property can handle nulls, won't bomb out, cause you'll just be returning a 0 item collection, instead of a null.
Only the first query with Where is a database query. As soon as you apply a "greedy" operator like FirstOrDefault the query gets executed. The second query is performed in memory. If Object.Table2 is a collection (which it apparently is) and you don't have lazy loading enabled your code will crash because the collection is null. If you have lazy loading enabled a second query is silently executed to load the collection - the complete collection and the filter is executed in memory.
You query should instead look like #adrift's code which would really be only one database query.