DbSet.Local is empty aftering adding to it - entity-framework

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.

Related

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

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

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

Entity Framework DeleteObject query a lot of items

I have a problem trying to delete an object with Entity Framework, I previously query the context to get a list of objects I need to delete, then one by one I call deleteobject
IQueryable result = context.CustomObjects.Where(t=>t.Property = something)
foreach (CustomObject customObj in result)
{
context.DeleteObject(customObj);
}
When I call DeleteObject EF executes a weird query, something like that:
exec sp_executesql N'SELECT
[Extent1].[Value1] AS [Value1],
[Extent1].[Value2] AS [Value2],
[Extent1].[Value3] AS [Value3],
FROM [CustomObject] AS [Extent1]
WHERE [Extent1].[ID] = #EntityKeyValue1',N'#EntityKeyValue1 int',#EntityKeyValue1=59
This query seems to search all the object with ID = something, but ID it is just part of the entity key that is indeed composed by 3 fields, so it attaches like n thousands items and make the process very slow, that is a behavior I can't understand, I always deleted object in this way and I have never had such a problem
can someone have an idea?
Thanks
You could be fetching mutiple objects as defined by your where query. Also for each object you fetch, you will be fetching all fields on the object CustomObject.
The query thats being executed is a select query so this confirms the above behaviour.
If you want better performance then I recommend that you do something like this:
var entityToDelete = new SomeEntity();
SomeEntity.PK = 12;
var context = new YourContextntities();
context.YourEntitites.Attach(entityToDelete);
context.YourEntitites.Remove(entityToDelete);
context.SaveChanges();

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.

Why "EntityKey does not match the corresponding value in the EntityKey"?

First I'd like to show the corresponding code snippet. When it comes to objCtx.AttachTo() it throws me an error:
Error: "The object cannot be attached because the value of a property that is a part of the EntityKey does not match the corresponding value in the EntityKey."
// convert string fragIds to Guid fragIds
var fragIdsGuids = docGenResult.FragIds.Select(c => new Guid(c)).ToList();
//add each fragment to document))))
foreach (Guid fragIdsGuid in fragIdsGuids)
{
var fragment = new Fragment() { EntityKey = new EntityKey("DocTestObjectContext.Fragments", "ID", fragIdsGuid) };
objCtx.AttachTo("Fragments", fragment);
}
objCtx.SaveChanges();
I've checked everything and I'm not missing any primary key.
However I need some words to explain why I think I have to do it this way.
I'm using EF4 in a C# Environment.
I have a many to many relationship between two tables, Document and Fragments(Primary key "ID") (Documents can have many fragments and a fragment can be a part of many documents)
The Entity Model works fine for me.
However when I try to add a new document to the DB I already have the IDs of the related Fragments in my hand. For adding a new document to the DB I have to call each Fragmentobject and add it to the mapped reference in my document-object. This is a bottleneck because a document can have more than 1000 fragments. The Consequence is that I need 1sec per document. Not much, but I have to create more than 3000 documents and saving this second would result in more speed.
Hopefully you know what's wrong in here.
Thanks.
Thomas
1st edit:
here is the solution wich actually works. I would like to avoid to load all the fragments and instead just save the fragment GUID I already have in the mapping table.
// convert string fragIds to Guid fragIds
var fragIdsGuids = docGenResult.FragIds.Select(c => new Guid(c)).ToList();
// get responding entities from Fragment table
var fragmentList = objCtx.Fragments.Where(c => fragIdsGuids.Contains(c.ID)).ToList();
foreach (var fragment in fragmentList)
{
doc.Fragment.Add(fragment);
}
objCtx.SaveChanges();
2nd edit:
I have the feeling that it is not really clear what I try to do.
However I would like to link/reference existing fragments in a Fragment-table to a coressponding Document in a Document table. The Document I'd like to reference is a new one. The document to Fragment table has an many to many relationship. This relationship has a linking table on the database. In the model it is correctly modeled as a many to many relationship. That's fine.
So far so good. What works is what you can see under my first edit. I have to load all the necessary fragments for a document by their id
// get responding entities from Fragment table
var fragmentList = objCtx.Fragments.Where(c => fragIdsGuids.Contains(c.ID)).ToList();
After that I'm able to add them to my document entity:
foreach (var fragment in fragmentList)
{
doc.Fragment.Add(fragment);
}
But why the hell do I have to load the whole entity (fragments) only to link it to a new document. Why do not tell the EntityStateManager "Dude, here you have some Fragment IDs, link them!"?
Further I tried to follow the MSDN article mentioned by Adrian in the comments. This doesn't worked out for me.
I'll try this:
var fragment = new Fragment {ID = fragIdsGuid};
//fragment.EntityKey.Dump(); // -- this should be null
objCtx.AttachTo("Fragments", fragment);
//fragment.EntityKey.Dump(); // -- shows the EntityKey object, created after the object is attached
The Dump function is from LinqPad